TypeScript泛型报错:类型'{}'无法赋值给类型'Keys<T>'原因排查
为何TypeScript泛型代码报错:Type '{}' is not assignable to type 'Keys'?
我无法理解下述TypeScript泛型代码为何报错:Type '{}' is not assignable to type 'Keys<T>'。
报错代码如下:
type Keys<T extends string|symbol>={ [key in T]: string; }; const foo = <T extends string|symbol>()=>{ const a:Keys<T> = {} return a }
此外,手动将泛型T替换为string或symbol类型时,代码无报错,仅会提示“T已声明但未使用”的警告,示例代码如下:
替换为string的情况:
type Keys<T extends string|symbol>={ [key in T]: string; }; const foo = <T extends string|symbol>()=>{ const a:Keys<string> = {} return a }
替换为symbol的情况:
type Keys<T extends string|symbol>={ [key in T]: string; }; const foo = <T extends string|symbol>()=>{ const a:Keys<symbol> = {} return a }
报错原因分析
- 当
T是泛型参数时,TypeScript无法预知T具体包含哪些键。Keys<T>的定义是所有属于T的键都必须存在,且对应值的类型为string。空对象{}不包含任何键,显然无法满足任意T的要求——比如如果调用foo<"id">(),Keys<T>就会变成{ id: string },空对象完全不符合这个类型。 - 而直接指定
T为string或symbol时,Keys<string>等价于带字符串索引签名的类型{ [key: string]: string },空对象{}是合法的:索引签名只约束“如果存在键,键的类型必须是string,值的类型必须是string”,空对象没有键,自然符合要求。Keys<symbol>同理,对应带symbol索引签名的类型,空对象也合法。
解决方法
方法1:使用类型断言
如果确定后续会为对象补充所需的键,可以用类型断言告诉TypeScript空对象可以赋值给Keys<T>:
type Keys<T extends string|symbol>={ [key in T]: string; }; const foo = <T extends string|symbol>()=>{ const a = {} as Keys<T> return a }
方法2:将Keys<T>的键改为可选
修改类型定义,让所有键变为可选属性,这样空对象就符合类型要求了:
type Keys<T extends string|symbol>={ [key in T]?: string; }; const foo = <T extends string|symbol>()=>{ const a:Keys<T> = {} return a }
内容的提问来源于stack exchange,提问作者Make Cheats
相关产品推荐
相关产品推荐

