Dan*_*elM 10 typescript conditional-types typescript2.8
在TypeScript中使用新的条件类型(或者可能是另一种技术),有没有办法根据修饰符从界面中选择某些属性?例如,有......
interface I1 {
readonly n: number
s: string
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个基于前一个类型的新类型,如下所示:
interface I2 {
s: string
}
Run Code Online (Sandbox Code Playgroud)
jca*_*alz 28
更新2018-10:@MattMcCutchen已经想通了,这是可以检测readonly场(以下无效被撞击出通道),如图这个答案.这是一种构建它的方法:
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];
Run Code Online (Sandbox Code Playgroud)
如果要从界面中提取可写字段,可以一起使用上述WritableKeys定义Pick:
interface I1 {
readonly n: number
s: string
}
type I2 = Pick<I1, WritableKeys<I1>>;
// equivalent to { s: string; }
Run Code Online (Sandbox Code Playgroud)
万岁!
因为readonly,我认为你不能提取那些.我以前看过这个问题,然后就不可能了; 而且我认为没有任何改变.
由于编译器没有合理地检查readonly属性,因此您始终可以将a分配{readonly n: number}给a {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 {}
Run Code Online (Sandbox Code Playgroud)
但你不能.在最初命名为" readonly修饰符是一个笑话"的GitHub问题中有一些有趣的讨论.
抱歉! 祝好运.
对于可选属性,您确实可以检测它们,从而提取或排除它们.这里的见解是{}延伸{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}
Run Code Online (Sandbox Code Playgroud)
这很好.
最后,我不知道,如果你希望能够做的东西,唯一的类属性修改器一样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}
Run Code Online (Sandbox Code Playgroud)
但是,提取的private或protected性质可能是不可能的,因为同样的原因,排除他们是如此的简单:keyof Foo没有它们.对于所有这些,包括abstract,你不能将它们添加到类型别名的属性(它们是仅类修饰符),所以我没有想到要触摸它们.
好的,希望有所帮助.
| 归档时间: |
|
| 查看次数: |
2034 次 |
| 最近记录: |