为了提高可读性,我希望一个转换器采用任何类型扩展Record<string,>并且返回一个类型,使不可定义的键成为可选的,显然保留其余的键。
ie:
// I want to turn this
type WithUndefined = {
a: string,
b: number | undefined,
c: boolean | undefined,
};
// Into this
type WithoutUndefined = {
a: string,
b?: number,
c?: boolean,
}
我已经找到了这样做的方法,但是对于我认为很简单的事情来说,它似乎有点复杂。如此之多,甚至VSCode都不能在覆盖层中自行解析类型,使其阅读起来很烦人,完全破坏了目标。
type OnlyKeepsDefined<T extends Record<string, any>> = Pick<
T,
{ [Key in keyof T]: undefined extends T[Key] ? never : Key }[keyof T]
>;
type OnlyKeepsUndefined<T extends Record<string, any>> = Pick<
T,
{ [Key in keyof T]: undefined extends T[Key] ? Key : never }[keyof T]
>;
type RemoveUnionUndefined<T extends Record<string, any>> = {
[Key in keyof T]: undefined extends T[Key] ? Exclude<T[Key], undefined> : T[Key];
};
type UndefinedToOptional<T extends Record<string, any>> = OnlyKeepsDefined<T> &
RemoveUnionUndefined<Partial<OnlyKeepsUndefined<T>>>;
type TestType = {
a: string;
b: number | undefined;
c: undefined;
};
type FilteredTestType = UndefinedToOptional<TestType>;
// Valid
const a: FilteredTestType = { a: "a" };
const b: FilteredTestType = { a: "a", b: 1 };
const c: FilteredTestType = { a: "a", b: 1, c: undefined };
有什么好的建议吗?
您可以使用Id
类型来解决打印类型,使其平坦:
type Id<T> = {} & {
[P in keyof T]: T[P]
}
操场上联系
对于更简单的版本,我们可以创建一个使用as
类过滤键的版本,但是仍然需要可选字段和必选字段的映射之间的交集,所以不确定它是否一定更简单
type UndefinedToOptional<T extends Record<string, any>> = {
// We keep only keys that have undefined in the type and make them optional
[P in keyof T as undefined extends T[P]? P: never]?: T[P]
} & {
// We keep only keys that do not have undefined in the type
[P in keyof T as undefined extends T[P]? never: P]: T[P]
}
操场上联系