首页 > 解决方案 > TypeScript - 无法将字符串分配给通用对象的字符串值属性

问题描述

在 TypeScript 3.5.2 中,我编写了一个映射类型AssignableKeys<T>,它生成所有类型的字符串值键的联合T(即,所有键T[K]都是字符串)。

此映射类型正确地防止将非字符串值属性分配给类型为 的变量AssignableKeys<T>

// Return a union of all keys in `T` that correspond to 
// properties that can be assigned a value of type `TValue`
export type AssignableKeys<T, TValue> = {
  [Key in keyof T]: TValue extends T[Key] ? Key : never
}[keyof T];

interface IObj {
    A: string,
    B: number,
}

// myKey must be a string-valued property of obj.
let myKey: AssignableKeys<IObj, string>;

// This works fine. "A" is a string-valued key of obj.
myKey = "A";

// This is an error (as expected). "B" is NOT a string-valued key of IObj.
myKey = "B";

但是,将字符串分配给与这些字符串值键之一对应的属性会失败并出现错误:

function setProp<T>(obj: T, key: AssignableKeys<T, string>) {
  obj[key] = "banana"; // typescript error (quoted below)
}

类型 '"banana"' 不可分配给类型 'T[{ [Key in keyof T]: T[Key] extends string ? 关键:从不;}[keyof T]]'。ts(2322)

据我了解,任何字符串都应该可以分配给obj[key]因为string extends obj[key]是真的。

我只是想知道这是否是我的语法或对类型系统的理解的一些错误,或者它是否是 TypeScript 的静态类型分析的限制(或一般静态类型分析的限制)。

当然,我可以使用以下命令强制代码工作as any

function setProp<T>(obj: T, key: AssignableKeys<T, string>) {
  obj[key] = "banana" as any; // no error
}

const myObj: IObj = { A: "", B: 5 };
setProp(myObj, "A"); // great
setProp(myObj, "B"); // error (as expected)

但我想知道为什么打字稿不喜欢原始形式的代码。

谢谢!

标签: typescriptgenericsstatic-analysistypescript2.0typescript-generics

解决方案


推荐阅读