TypeScript报错:Type 'string'无法赋值给'never'类型.ts(2322) 求解
错误原因
当你给Obj传入包含两个Domain的类型时,Group<events, keyof events>中的domain是"Domain0" | "Domain1"联合类型。此时events[domain]会变成两个Enum类型的联合:Enum<"Event0_0" | "Event0_1" | "Event0_2"> | Enum<"Event1_0" | "Event1_1" | "Event1_2">。
而keyof对联合类型取键时,只会保留所有分支共有的键——这两个Enum的键完全不重叠,所以keyof events[domain]的结果就是never,这就是报错Type 'string' is not assignable to type 'never'的根源。
当只有一个Domain时,domain是单一类型,events[domain]也是单一的Enum,keyof能正确取出对应的事件键,因此不会报错。
修正代码
需要把Obj中的Group类型改成联合类型,让每个Domain和对应的Event形成独立的类型分支,避免混在一起导致的交集运算问题。修改Obj接口的定义即可:
type Enum<K extends PropertyKey> = { [key in K]: key; }; type Events = Record<string, Enum<string>>; interface Group<events extends Events, domain extends keyof events> { Domain: domain; Event: keyof events[domain]; }; // 调整Obj的Group类型为各Domain对应Group的联合 interface Obj<events extends Events> { Group: { [D in keyof events]: Group<events, D> }[keyof events]; }; const obj: Obj<{ Domain0: Enum<"Event0_0" | "Event0_1" | "Event0_2">, Domain1: Enum<"Event1_0" | "Event1_1" | "Event1_2">, }> = { Group: { Domain: "Domain0", Event: "Event0_0" }, // 正常通过类型检查 }; // 也可赋值另一个Domain的事件 const obj2: Obj<{ Domain0: Enum<"Event0_0" | "Event0_1" | "Event0_2">, Domain1: Enum<"Event1_0" | "Event1_1" | "Event1_2">, }> = { Group: { Domain: "Domain1", Event: "Event1_2" }, // 同样正常 };
代码说明
{ [D in keyof events]: Group<events, D> }会生成一个以每个Domain为键、对应Group类型为值的映射类型,再通过[keyof events]索引访问,把所有值类型提取出来形成联合类型。最终Group会变成Group<..., "Domain0"> | Group<..., "Domain1">,TypeScript能正确识别每个分支中Domain和Event的对应关系,不会再出现never类型问题。
内容的提问来源于stack exchange,提问作者striderhobbit

