You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:20:40