假设你有一个泛型函数
wrap()
T
并返回类型为的值
{a: T}
,例如:
function wrap<T>(x: T) {
return ({ a: x });
}
things
还有电话
things.map(wrap)
,您将得到一个弱类型函数,如您所注意到的:
const mapWrapWeaklyTyped = <T extends any[]>(...things: T) => things.map(wrap);
{a: any}
. 这是事实,但不是很有用:
const weak = mapWrapWeaklyTyped(1, "two", new Date());
try {
weak[2].a.toUpperCase();
} catch (e) {
console.log(e);
}
2
指
Date
而不是包装好的
string
. 我必须等到运行时才能看到问题。
standard TypeScript library's typing
对于
Array.prototype.map()
interface Array<T> {
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}
东西.地图(包装)
,编译器将推断单个
U
{a:任何}
东西
T extends any[]
,所有编译器都知道
any
一般的
你可以给我打字
这将处理
callbackfn
type constructors
,当前不直接支持哪个TypeScript(请参见
microsoft/TypeScript#1213
相关功能请求)。
回电
,(例如。,
(x: T) => {a: T}
mapped array/tuple types
.
这里是:
const mapWrapStronglyTyped = <T extends any[]>(...things: T) => things.map(wrap) as
{ [K in keyof T]: { a: T[K] } };
K
的
T
数组,然后
T[K]
{a: T[K] }
.
map()
不预期此特定的泛型映射函数,必须使用
type assertion
进行类型检查。如果您只关心编译器在没有类型断言的情况下无法验证这一点,那么这实际上是在TypeScript中没有更高级类型的情况下所能做的最好的事情。
您可以在与前面相同的示例中进行测试:
const strong = mapWrapStronglyTyped(1, "two", new Date());
try {
strong[2].a.toUpperCase(); // compiler error, Property 'toUpperCase' does not exist on type 'Date'
} catch (e) {
console.log(e); // strong[2].prop.toUpperCase is not a function
}
// oops, I meant to do this instead!
console.log(strong[1].a.toUpperCase()); // TWO
现在编译器捕捉到错误并告诉我
日期
对象没有
toUpperCase
方法。万岁!
type MapToMyInterface<T extends any[]> = {
[K in keyof T]: T[K] extends Array<infer U> ? { a: U } : { a: T[K] }
}
有点奇怪,因为你在做地图
两次
;除非传入数组,否则没有理由进行检查
T[K]
K
是它的索引。所以我得说回来吧
{a: T[K]}
除非我错过了重要的事情。
Playground link to code