TypeScrip条件类型-筛选出只读属性/仅选择必需属性 [英] TypeScript conditional types - filter out readonly properties / pick only required properties
本文介绍了TypeScrip条件类型-筛选出只读属性/仅选择必需属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
interface I1 {
readonly n: number
s: string
}
我想在前一个类型的基础上创建一个新类型,如下所示:
interface I2 {
s: string
}
推荐答案
更新2018-10:@MattMcCutchen发现可以检测readonly
字段(使下面删除的段落无效),如this answer所示。以下是构建它的方法:
type IfEquals<X, Y, A=X, B=never> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;
type WritableKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];
type ReadonlyKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];
如果要从接口提取可写字段,可以同时使用上述WritableKeys
定义和Pick
:
interface I1 {
readonly n: number
s: string
}
type I2 = Pick<I1, WritableKeys<I1>>;
// equivalent to { s: string; }
万岁!
<罢工>
对于readonly
,我认为您无法提取它们。我已经looked at this issue before,这在当时是不可能的;我认为一切都没有改变。
readonly
properties,您始终可以将{readonly n: number}
分配给{n: number}
,反之亦然。因此,明显的TSv2.8条件类型检查不起作用。例如,如果{n: number}
不被认为可分配给{readonly n: number}
,则可以执行如下操作:
// does not work, do not try this
type ExcludeReadonlyProps<T> = Pick<T,
{ [K in keyof T]-?:
({ readonly [P in K]: T[K] } extends { [P in K]: T[K] } ? never : K)
}[keyof T]>
type I2 = ExcludeReadonlyProps<I1> // should be {s: string} but is {} 🙁
但你不能。在GitHub issue originally named "readonly
modifiers are a joke"中有一些关于这方面的有趣的讨论。
对不起!祝好运。
对于可选属性,您确实可以检测到它们,从而提取或排除它们。这里的洞察是{}
扩展{a?: string}
,但{}
不扩展{a: string}
,甚至{a: string | undefined}
。下面是如何构建一种从类型中删除可选属性的方法:
type RequiredKeys<T> = { [K in keyof T]-?:
({} extends { [P in K]: T[K] } ? never : K)
}[keyof T]
type OptionalKeys<T> = { [K in keyof T]-?:
({} extends { [P in K]: T[K] } ? K : never)
}[keyof T]
type ExcludeOptionalProps<T> = Pick<T, RequiredKeys<T>>
type I3 = {
a: string,
b?: number,
c: boolean | undefined
}
type I4 = ExcludeOptionalProps<I3>;
// {a: string; c: boolean | undefined} 🙂
所以这很好。
最后,我不知道您是否希望使用
public
、private
、protected
和abstract
等仅限类的属性修饰符,但我对此表示怀疑。碰巧private
和protected
类属性很容易被排除,因为它们不存在于keyof
:中
class Foo {
public a = ""
protected b = 2
private c = false
}
type PublicOnly<T> = Pick<T, keyof T>; // seems like a no-op but it works
type PublicFoo = PublicOnly<Foo>; // {a: string} 🙂
但提取private
或protected
属性可能是不可能的,原因与排除它们是如此容易:keyof Foo
没有它们。对于包括abstract
在内的所有这些元素,您不能将它们添加到类型别名中的属性中(它们是仅限类的修饰符),因此我想不出什么办法来触及它们。
好的,希望这会有帮助。
这篇关于TypeScrip条件类型-筛选出只读属性/仅选择必需属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文