Mat*_*hew 5 typescript typescript-generics
在 TypeScript 中,如果对象类型包含类型为 的字段never,则无法真正实例化该类型的对象。例子:
type x = { a: string; b: never };
const xx: x = { a: "asd" }; // property 'b' is missing
Run Code Online (Sandbox Code Playgroud)
我认为能够删除所有无法分配的字段可能很有用(实际上我主要认为这将是一个有趣的挑战),我的解决方案是:
/** Recursively decays all fields that are of type `never` from `T`.
* @example DecayNever<number> // yields number
* @example DecayNever<{ x: number; y: string; z: never }> // yields { x: number; y: string }
* @example DecayNever<{ x: number; y: { z: never } }> // yields { x: number }
* @example DecayNever<{ x: number; y: { z: never, w: string } }> // yields { x: number, y: { w: string } }
* @example DecayNever<{ a: { b: { c: never } } }> // yields never
*/
export type DecayNever<T> = T extends Record<string | number | symbol, unknown>
? FilteredKeys<{ [K in keyof T]: DecayNever<T[K]> }> extends never
? never
: Pick<DecayNeverType<T>, FilteredKeys<DecayNeverType<T>>>
: T;
type DecayNeverType<T> = { [K in keyof T]: DecayNever<T[K]> };
/** Returns a union of all keys of `T` where `T[K]` is not `never` */
type FilteredKeys<T> = { [K in keyof T]: T[K] extends never ? never : K }[keyof T];
type t_1 = DecayNever<number>;
type t_2 = DecayNever<{ x: number; y: string; z: never }>;
type t_3 = DecayNever<{ x: number; y: { z: never } }>;
type t_4 = DecayNever<{ x: number; y: { z: never, w: string } }>;
type t_5 = DecayNever<{ a: { b: { c: never } } }>;
Run Code Online (Sandbox Code Playgroud)
这似乎确实有效,尽管它非常非常不稳定。我很惊讶没有内置方法可以做到这一点,但是有更好的方法吗?感觉非常不优雅,并且检查以确保FilteredKeys<...>不是never因为Pick<T, never>结果是类型{}(我认为有点类似于any?)。
| 归档时间: |
|
| 查看次数: |
536 次 |
| 最近记录: |