【问题标题】:Unable to understand the semantics of keyof in TypeScript无法理解 TypeScript 中 keyof 的语义
【发布时间】:2020-01-11 00:02:45
【问题描述】:

我有下面这个简单的例子说明K extends keyof T是在哪里声明的,但是为findMember推断的返回类型的结果是不同的,我真的不明白为什么会有这样的差异。

我还创建了一个指向 TypeScript Playground HERE的链接

class Group1<T> {
    findMember<K extends keyof T = keyof T>(name: K): T[K] {
        return {} as T[K];
    }
}

class Group2<T, K extends keyof T = keyof T> {
    findMember(name: K): T[K] {
        return {} as T[K];
    }
}

interface Person {
    firstName: string;
    lastName: string;
    age: number;
    addresses: Array<{
        street: string;
        city: string;
        zip: string;
    }>
}

const group1 = new Group1<Person>();
// Inferred type is Array<{ street: string; city: string; zip: string; }>;
const addresses1 = group1.findMember('addresses');

const group2 = new Group2<Person>();
// Inferred type is string | number | Array<{ street: string; city: string; zip: string; }>;
const addresses2 = group2.findMember('addresses');

【问题讨论】:

    标签: typescript type-inference keyof


    【解决方案1】:

    group1.findMember('addresses')中,K可以推断为"addresses",所以返回Person["addresses"]

    group2.findMember('addresses') 中,K 是来自顶级类声明的类型参数。 使用其默认类型keyof TT 的所有键),因为您没有指定K,当使用const group2 = new Group2&lt;Person&gt;(); 创建实例时。所以你最终得到了返回类型Person["firstName" | "lastName" | "age" | "addresses"],它是所有可能的属性值的联合。

    如果你使用const group2 = new Group2&lt;Person, "addresses"&gt;(),结果应该是一样的。

    【讨论】:

    • 这是有道理的,有没有什么方法可以为Group1 使用我为Group2 提供的东西而不使findMember 成为通用方法?
    • 也许是this(不确定您想要什么)?两者之间的唯一区别是定义泛型的位置。
    • 我想要的是能够键入检查我传递给findMember 的内容而不使findMember 泛型,并且我希望能够传递T 中存在的每个属性,并且让 TypeScript 为我推断 K
    • 我认为没有它是不可能的。 keyof 将始终返回所有键的并集,T[keyof T] 返回所有可能的属性值。您必须在某处设置通用约束以将选择限制为所选属性。此类型参数可以在类或方法上,您还可以像示例中一样包含一些实例状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    相关资源
    最近更新 更多