TypeScript 元编程:推断私有类型?
TypeScript metaprogramming: inferring private type?
是否可以通过通用方式推断私有成员的类型?
有这个class:
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 }
,它没有 public 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
的类型,但有没有办法以通用的方式(使用更多元编程)来做到这一点?
背景:我想创建花哨的装饰器,为除被装饰者之外的其他成员提供保证。其中一些成员可能是私有的。
.
但是,正如您所指出的,如果您知道名称,则无论如何都可以潜水并获得它。
鉴于我们可以更接近:
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
可以被任何字符串索引,以允许我们检查其不可枚举的键。如果我们将它与索引签名相交,我们可以告诉打字稿检查任何字符串 属性.
是安全的
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
理想情况下,DummyMemberType<'bad'>
将是一个类型错误,但无法将密钥限制为 keyof Dummy
,我不明白这怎么可能。返回 never
可能会尽善尽美。
是否可以通过通用方式推断私有成员的类型?
有这个class:
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 }
,它没有 public 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
的类型,但有没有办法以通用的方式(使用更多元编程)来做到这一点?
背景:我想创建花哨的装饰器,为除被装饰者之外的其他成员提供保证。其中一些成员可能是私有的。
但是,正如您所指出的,如果您知道名称,则无论如何都可以潜水并获得它。
鉴于我们可以更接近:
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
可以被任何字符串索引,以允许我们检查其不可枚举的键。如果我们将它与索引签名相交,我们可以告诉打字稿检查任何字符串 属性.
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
理想情况下,DummyMemberType<'bad'>
将是一个类型错误,但无法将密钥限制为 keyof Dummy
,我不明白这怎么可能。返回 never
可能会尽善尽美。