【问题标题】:TypeScript metaprogramming: inferring private type?TypeScript 元编程:推断私有类型?
【发布时间】:2021-05-21 23:01:12
【问题描述】:

是否可以以通用方式推断私有成员的类型?

有这个课程:

class Dummy {
    private num: number; // I want to get the type of this: number
    str: string; // control group
}

我可以手动获取num字段的类型:

type DummyNumTypeWorks = Dummy['num']; // number -- yey, I'm happy. 

但我想用泛型来做到这一点。我有以下不起作用的示例。我明白为什么:Dummy 没有实现{ num: number },它没有公共num 成员。所以我正在寻找替代品。

// Inferring from Dummy
type DummyMemberType<TMember extends string> = Dummy extends { [key in TMember]: infer R } ? R : never;
type DummyStrMember = DummyMemberType<'str'>; // string
type DummyNumMember = DummyMemberType<'num'>; // never :(

// Inferring from the member name
type DummyMemberType2<TMember extends string> = TMember extends keyof Dummy ? Dummy[TMember] : never;
type DummyStrMember2 = DummyMemberType2<'str'>; // string
type DummyNumMember2 = DummyMemberType2<'num'>; // never :(

我明白为什么这些不起作用。

我的问题:虽然我可以手动推断 num 的类型,但有没有办法以通用方式(使用更多元编程)来做到这一点?

背景:我想创建精美的装饰器,以保证除了被装饰的成员之外的其他一些成员。其中一些成员可能是私有的。

【问题讨论】:

    标签: typescript metaprogramming private


    【解决方案1】:

    Private members are not enumerable in keyof.

    但是,正如你所说,如果你知道这个名字,你无论如何都可以潜水并得到它。

    鉴于我们可以更接近:

    type DummyMemberType<TMember extends string> = Dummy[TMember];
    // Type 'TMember' cannot be used to index type 'Dummy'.(2536)
    
    type DummyStrMember = DummyMemberType<'str'>; // string
    type DummyNumMember = DummyMemberType<'num'>; // number
    type DummyBadMember = DummyMemberType<'bad'>; // unknown
    

    类型内部仍然存在类型错误,但DummyMemberType 现在可以正常使用。但是,如果您传入一个错误的密钥,您会得到unknown,这并不理想。


    所以我们需要使Dummy 可以被任何字符串索引,以允许我们检查其不可枚举的键。如果我们将它与索引签名相交,我们可以告诉 typescript 检查任何字符串属性是安全的。

    type DummyMemberType<TMember extends string> =
      (Dummy & { [key: string]: never })[TMember];
    

    您可以像这样抽象为泛型类型别名:

    type UniversallyIndexable<T> = T & { [key: string]: never }
    type DummyMemberType<TMember extends string> =
      UniversallyIndexable<Dummy>[TMember];
    

    现在它可以像你期望的那样工作了:

    type DummyStrMember = DummyMemberType<'str'>; // string
    type DummyNumMember = DummyMemberType<'num'>; // number
    type DummyBadMember = DummyMemberType<'bad'>; // never
    

    Playground


    理想情况下,DummyMemberType&lt;'bad'&gt; 将是一个类型错误,但无法将密钥限制为keyof Dummy,我不明白这怎么可能。返回never 可能会很好。

    【讨论】:

    • 谢谢你,特别是通用解决方案(UniversallyIndexable),我打算推广一下。
    猜你喜欢
    • 2018-07-03
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 2016-04-04
    相关资源
    最近更新 更多