假设我有以下类型:
interface Foo {
a?: string;
b: string;
}
Run Code Online (Sandbox Code Playgroud)
可以使用设置所有属性Required。
type Bar = Required<Foo>;
// Equivalent to
interface Bar {
a: string;
b: string;
}
Run Code Online (Sandbox Code Playgroud)
可以使用将所有属性设为可选Partial。
type Bar = Partial<Foo>;
// Equivalent to
interface Bar {
a?: string;
b?: string;
}
Run Code Online (Sandbox Code Playgroud)
我想做一个通用类型,而不是翻转所有属性的可选标志。
type Bar = Flip<Foo>;
// Equivalent to
interface Bar {
a: string;
b?: string;
}
Run Code Online (Sandbox Code Playgroud)
为实现Partial和Required相当简单明了,但这种Flip类型需要知道哪些属性Foo是可选的,这是必需的。是否可以使用泛型读取此修改内容?
一些背景:我相信这defaultProps在React 中将是有用的类型。
对于您所说的问题(其中Foo没有索引签名),您可以这样定义Flip(我称之为FlipOptional):
type OptionalKeys<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? K : never
}[keyof T];
type FlipOptional<T> = (Required<Pick<T, OptionalKeys<T>>> &
Partial<Omit<T, OptionalKeys<T>>>) extends infer O
? { [K in keyof O]: O[K] }
: never;
Run Code Online (Sandbox Code Playgroud)
首先,我们必须确定的哪些键T是可选的。没有简单的内置方法可以执行此操作,但是上面的OptionalKeys类型别名可以通过检查哪些单属性扩展T是弱类型来工作,如对相关问题的回答所述。索引签名将这一点弄乱了,因此,如果您需要对具有索引签名的类型进行操作,则需要更复杂的东西(在链接的答案中也有介绍)。
一旦确定了哪些键是可选的,就可以轻松地构造一个与您想要的键等效的类型,Pick并Omit与Partial和Required以及一个和一个交集:Required<Pick<T, OptionalKeys<T>>> & Partial<Omit<T, OptionalKeys<T>>>。唯一的问题是这种类型相对难看。如果将类型写为单个对象类型,那就更好了。
在这里,我使用以下形式的带条件类型推断的技巧。假设我们有一个Ugly包含许多交集和映射的类型。为了使它漂亮,我们可以做
type Pretty = Ugly extends infer O ? {[K in keyof O]: O[K]} : never
Run Code Online (Sandbox Code Playgroud)
这里,Ugly本质上是“复制”到O参数,该参数被映射而不更改任何内容。就输出而言,这基本上是无操作的,但是如果可能的话,结果将是单个对象类型。
让我们尝试一下:
interface Foo {
a?: string;
b: string;
}
type Bar = FlipOptional<Foo>;
/* type Bar = {
a: string;
b?: string | undefined;
} */
type FooAgain = FlipOptional<Bar>;
/* type FooAgain = {
b: string;
a?: string | undefined;
} */
type MutuallyAssignable<T extends U, U extends V, V = T> = true;
type FooAgainIsFoo = MutuallyAssignable<Foo, FooAgain>; // okay
Run Code Online (Sandbox Code Playgroud)
这一切看起来都不错。 Bar是您所期望的,并FlipOptional<Bar>提供了等效于的类型Foo。
好的,希望对您有所帮助。祝好运!
| 归档时间: |
|
| 查看次数: |
72 次 |
| 最近记录: |