如果TypeScript中有接口,如何在数组中指定泛型
我有一个函数,它接受一系列规范作为参数。这些规范的形状已定义,但值可以是任何形式。但是-我想提供一个泛型,让TypeScript根据传入函数的规范推断类型。下面是一个非常基本的示例:如果TypeScript中有接口,如何在数组中指定泛型,typescript,generics,Typescript,Generics,我有一个函数,它接受一系列规范作为参数。这些规范的形状已定义,但值可以是任何形式。但是-我想提供一个泛型,让TypeScript根据传入函数的规范推断类型。下面是一个非常基本的示例: 接口规范{ 价值:你的类型; } 函数doStuff(规格:Spec[]):T[]{ 返回specs.map(spec=>spec.value); } 常量mySpecs=[ {value:1}, {value:'two'}, {value:[1,2,3]}, ]; 常量值=doStuff(mySpecs); 我
接口规范{
价值:你的类型;
}
函数doStuff(规格:Spec[]):T[]{
返回specs.map(spec=>spec.value);
}
常量mySpecs=[
{value:1},
{value:'two'},
{value:[1,2,3]},
];
常量值=doStuff(mySpecs);
我知道这里不能真正推断类型,因为它们都是不同的,但是我可以以某种方式将它们作为类型显式地添加到doStuff泛型中吗。类似于以下伪代码:
function doStuff<T>(specs: <Spec<t> for t of T>): <t for t of T> {
return specs.map(spec => spec.value);
}
const values = doStuff<[number, string, number[]]>(mySpecs);
函数doStuff(规格:):{
返回specs.map(spec=>spec.value);
}
常量值=doStuff(mySpecs);
您必须提供YourType
的联合类型定义,以使其正常工作:
const mySpecs = [
{value: 1},
{value: 'two'},
{value: [1, 2, 3]},
];
type YourType = number | string | number[];
interface Spec<YourType> {
value: YourType;
}
function doStuff<T>(specs: Spec<T>[]): T[] {
return specs.map(spec => spec.value);
}
const values = doStuff<YourType>(mySpecs);
console.log(values);
const mySpecs=[
{value:1},
{value:'two'},
{value:[1,2,3]},
];
键入YourType=number | string | number[];
接口规范{
价值:你的类型;
}
函数doStuff(规格:Spec[]):T[]{
返回specs.map(spec=>spec.value);
}
常量值=doStuff(mySpecs);
console.log(值);
TypeScript 3.1引入了对使用的支持,因此如果您有一个像[1,2,3]
这样的类型,并将一个像{[K in keyof T]:Spec}
这样的映射类型应用到它,它将变成[Spec,Spec,Spec]
。因此,函数的签名可以是这样的:
declare function doStuff<T extends readonly any[]>(
specs: { [K in keyof T]: Spec<T[K]> } | []
): T;
const mySpecs = [
{ value: 1 },
{ value: 'two' },
{ value: [1, 2, 3] },
] as const;
/* const mySpecs: readonly [
{ readonly value: 1; }, { readonly value: "two"; }, { readonly value: readonly [1, 2, 3];
}] */
const moreValues = doStuff(mySpecs);
// const moreValues: readonly [1, "two", readonly [1, 2, 3]]
如果您想在使用mySpecs
的两行中分别执行此操作,您可能应该告诉编译器不要忘记mySpecs
是一种元组类型,如下所示:
declare function doStuff<T extends readonly any[]>(
specs: { [K in keyof T]: Spec<T[K]> } | []
): T;
const mySpecs = [
{ value: 1 },
{ value: 'two' },
{ value: [1, 2, 3] },
] as const;
/* const mySpecs: readonly [
{ readonly value: 1; }, { readonly value: "two"; }, { readonly value: readonly [1, 2, 3];
}] */
const moreValues = doStuff(mySpecs);
// const moreValues: readonly [1, "two", readonly [1, 2, 3]]
在这里,我使用了TypeScript 3.4+来保持mySpecs
的类型狭窄。。。可能它太窄了,因为所有内容都变成了只读。但这取决于你的工作
这将是答案的结尾,但遗憾的是,编译器无法验证
doStuff()
的实现是否符合签名:
return specs.map(spec => spec.value); // error! not callable
解决这一问题的最简单方法是首先明智地说服编译器,specs
有一个可用的map
方法(说它是Spec)