为什么 Typescript Omit/Pick 擦除符号
Why Typescript Omit/Pick erase Symbols
首先我是 TS 的新手。并尝试为我自己的项目做一些 utilities。
但是当我处理类型映射时。我发现 Pick/Omit/Exclude 和其他键入指令会删除带有符号键的字段。作为此处的代码:
interface T { a: number;[Symbol.iterator](): IterableIterator<number>; }
type NoA=Omit<T,'a'>;
NoA 将是一个空类型。但是我正在其中扩展一个迭代器。
为什么会这样?有没有逛街的地方?
有关更多信息,我的库中的相关代码是:
export type Merg<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export type MergO<U extends object>
= (U extends object ? (k: U) => void : never) extends
(k: infer I) => void ? (I extends object ? I : object) : object;
export type Alter<T extends object, U extends object>
= Pick<T, Exclude<keyof T, keyof U>> & Pick<U, Extract<keyof T, keyof U>>;
export type Extra<T extends object, U extends object> = Pick<T, Exclude<keyof T, keyof U>>;
export type Common<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U>>;
export type Extend<T extends object, U extends object> = T & Omit<U, keyof T>;
export type Override<T extends object, U extends object> = Omit<T, keyof U> & U;
export type AlterOver<T extends object, U extends object, X extends object> = Alter<T, Extra<U, X>>;
export type ExtendOver<T extends object, U extends object, X extends object> = Extend<T, Extra<U, X>>;
export type OverrideOver<T extends object, U extends object, X extends object> = Override<T, Extra<U, X>>;
export type AlterLike<T extends object, U extends object, X extends object> = Alter<T, Common<U, X>>;
export type ExtendLike<T extends object, U extends object, X extends object> = Extend<T, Common<U, X>>;
export type OverrideLike<T extends object, U extends object, X extends object> = Override<T, Common<U, X>>;
基于@hackape 的解决方法,新的按类型排除可以是:
export type Exclude2<T extends object, U extends object> =
U extends { [Symbol.iterator]: any } ? Omit<T, keyof U>:
T extends { [Symbol.iterator]: infer IT } ? { [Symbol.iterator]: IT } & Omit<T, keyof U> : Omit<T, keyof U>;
就像评论中提到的@jcalz 一样,Symbol.iterator
被视为"well known symbol" 并从已解析的映射类型中排除。目前,打字稿将 Symbol.whatever
形式的任何表达式视为 "well known symbol".
解决方法:
interface T { b: boolean; a: number; [Symbol.iterator](): IterableIterator<number>; }
type Omit2<T, K extends keyof T> = T extends { [Symbol.iterator]: infer U } ? { [Symbol.iterator]: U } & Omit<T, K> : Omit<T, K>
type NoA = Omit2<T, 'a'>;
首先我是 TS 的新手。并尝试为我自己的项目做一些 utilities。 但是当我处理类型映射时。我发现 Pick/Omit/Exclude 和其他键入指令会删除带有符号键的字段。作为此处的代码:
interface T { a: number;[Symbol.iterator](): IterableIterator<number>; }
type NoA=Omit<T,'a'>;
NoA 将是一个空类型。但是我正在其中扩展一个迭代器。
为什么会这样?有没有逛街的地方?
有关更多信息,我的库中的相关代码是:
export type Merg<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export type MergO<U extends object>
= (U extends object ? (k: U) => void : never) extends
(k: infer I) => void ? (I extends object ? I : object) : object;
export type Alter<T extends object, U extends object>
= Pick<T, Exclude<keyof T, keyof U>> & Pick<U, Extract<keyof T, keyof U>>;
export type Extra<T extends object, U extends object> = Pick<T, Exclude<keyof T, keyof U>>;
export type Common<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U>>;
export type Extend<T extends object, U extends object> = T & Omit<U, keyof T>;
export type Override<T extends object, U extends object> = Omit<T, keyof U> & U;
export type AlterOver<T extends object, U extends object, X extends object> = Alter<T, Extra<U, X>>;
export type ExtendOver<T extends object, U extends object, X extends object> = Extend<T, Extra<U, X>>;
export type OverrideOver<T extends object, U extends object, X extends object> = Override<T, Extra<U, X>>;
export type AlterLike<T extends object, U extends object, X extends object> = Alter<T, Common<U, X>>;
export type ExtendLike<T extends object, U extends object, X extends object> = Extend<T, Common<U, X>>;
export type OverrideLike<T extends object, U extends object, X extends object> = Override<T, Common<U, X>>;
基于@hackape 的解决方法,新的按类型排除可以是:
export type Exclude2<T extends object, U extends object> =
U extends { [Symbol.iterator]: any } ? Omit<T, keyof U>:
T extends { [Symbol.iterator]: infer IT } ? { [Symbol.iterator]: IT } & Omit<T, keyof U> : Omit<T, keyof U>;
就像评论中提到的@jcalz 一样,Symbol.iterator
被视为"well known symbol" 并从已解析的映射类型中排除。目前,打字稿将 Symbol.whatever
形式的任何表达式视为 "well known symbol".
解决方法:
interface T { b: boolean; a: number; [Symbol.iterator](): IterableIterator<number>; }
type Omit2<T, K extends keyof T> = T extends { [Symbol.iterator]: infer U } ? { [Symbol.iterator]: U } & Omit<T, K> : Omit<T, K>
type NoA = Omit2<T, 'a'>;