TypeScript中将字符串数组赋值给keyof T数组为何编译成功?
问题成因
现有代码的类型校验失效核心是 TypeScript 泛型推断结合函数参数逆变特性导致的:
基础类型关系梳理
- 自定义
Entity类仅有id属性,因此keyof Entity的类型等价于字面量联合类型'id',selector函数的入参类型为('id')[] select函数的泛型T需要同时匹配两个入参的约束:- 第一个入参是函数类型
(arg: T) => any,传入selector时,由于函数参数属于逆变位点,仅要求T是('id')[]的父类型即可(即('id')[]可以赋值给T类型) - 第二个入参传入的
['name']默认被推导为string[]类型
- 第一个入参是函数类型
推断逻辑
TypeScript 会自动推导满足所有约束的最宽类型:string[]完全符合要求——('id')[]是string[]的子类型,满足第一个参数的逆变约束;['name']本身就是string[]类型,也匹配第二个入参的类型要求,因此编译不会触发报错。
解决方案
如果需要实现预期的类型校验,可以阻断泛型从第二个入参的位置推导,强制泛型仅从第一个函数参数的类型推导,TS 5.4及以上版本可以使用内置的NoInfer工具类型修改select定义:
declare function select<T>(fun: (arg: T) => any, arg: NoInfer<T>): any;
修改后调用select(selector, ['name'])就会抛出预期的Type '"name"' is not assignable to type '"id"'类型错误。
内容的提问来源于stack exchange,提问作者Rafi Henig
相关产品推荐
相关产品推荐

