我想做这样的事情:
interface Foo<T extends any>{
a: string;
b: T;
}
function createFunctions(items: Foo<any>[]) {
return items.map(item => () => {
return item.b;
});
}
const items = [
{
a: "hello",
b: "foo"
},
{
a: "world",
b: 909
}
];
const fns = createFunctions(items);
const a2: string = fns[0]();
const b2: string = fns[1](); //Should error - TypeScript should know it's a number
也就是说-我有一个类型为Foo
的类型,但是该类型可以是任何类型。
我现在有了这些Foos的列表,该列表可以是所有不同类型的,但是我知道它们的类型。
然后,我想创建一个匹配的功能列表,并对这些功能进行类型强制。
我在这里遇到的问题-这些函数将以具有“ any”类型的返回形式返回。如何执行返回类型?
答案 0 :(得分:1)
如果我对您的理解正确,则b
中的每个items
属性项都可以具有不同的类型。要保留每种类型,可能的解决方案是使用items
元组而不是数组,并为createFunctions
声明显式的mapped tuple返回类型:
interface Foo<T> { a: string; b: T; }
// we infer the items parameter via generic type parameter as tuple
// a mapped tuple type is used as return type
function createFunctions<T extends readonly Foo<any>[]>(items: T):
{ [K in keyof T]: () => T[K] extends Foo<any> ? T[K]["b"] : never } {
return items.map(item => () => {
return item.b;
}) as any
// TS cannot properly infer return type here (generics + conditional types + mapped tuple)
// alt cast: as unknown as { [K in keyof T]: () => T[K] extends Foo<any> ? T[K]["b"] : never }
}
items
元组类型通过const assertions保留:
const items = [
{ a: "hello", b: "foo" },
{ a: "world", b: 909 }
] as const // <--- preserve the tuple type here
const fns = createFunctions(items); // readonly [() => "foo", () => 909]
const a2: string = fns[0](); // works
const b2: string = fns[1](); // error, 909 expected
Here is an extended Playground that shows inference of multiple generic parameters