获取通用接口扩展
Get generic interface extension
考虑以下接口:
interface A {
name: string;
value: number;
sub: {
query: number[]
},
old: number;
}
interface B {
name: string;
value: string;
sub: {
query: string[]
},
new: boolean;
}
我正在寻找通用解决方案来获得 interface/type:
interface C extends B, A {
}
其中 C 类似于接口 D:
interface D {
name: string;
value: string;
sub: {
query: string[]
},
old: number;
new: boolean;
}
所以我可以有一个功能:
function merge<T, U>(t: T, u: U): interface C extends T, U {
// Merge objects
// ...
return obj;
}
它不一定是一个接口。 A 类型也可以(我认为)。
类型 A & B
不起作用,因为那时我有一个交集(例如 value
将是 number & string
类型)。
我使用这个 MergeReplace
类型来更准确地输入 Object.assign({}, T, S)
:
type MergeReplace<T, S> = Omit<T, keyof T & keyof S> & S;
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
如果您使用的是 < 2.8 的 TypeScript,Exclude
可以这样定义:
type Project<K extends string, T> = (T & {[x: string]: never})[K];
type Delete<T extends string, U extends string> = ({[P in T]: P} & {[P in U]: never});
type Exclude<T extends string, U extends string> = Project<T, Delete<T,U>>;
TypeScript playground with examples
注意 MergeReplace
是右偏的,所以如果 T
和 S
共享一个 属性 但类型不同,则 S
的类型是已选择。
查看 this TypeScript issue 了解更多信息。
我想我明白了:
type MergeRightBiased<TLeft, TRight> =
TLeft extends any[] ? TRight :
TRight extends any[] ? TRight :
TLeft extends object ?
TRight extends object ? {
// All properties of Left and Right, recursive
[P in keyof TLeft & keyof TRight]: MergeRightBiased<TLeft[P], TRight[P]>
} & {
// All properties of Left not in Right
[P in Exclude<keyof TLeft, keyof TRight>]: TLeft[P];
} & {
// All properties of Right not in Left
[P in Exclude<keyof TRight, keyof TLeft>]: TRight[P]
}
// Prefer Right
: TRight
: TRight;
感谢@Oblosys 的帮助!
考虑以下接口:
interface A {
name: string;
value: number;
sub: {
query: number[]
},
old: number;
}
interface B {
name: string;
value: string;
sub: {
query: string[]
},
new: boolean;
}
我正在寻找通用解决方案来获得 interface/type:
interface C extends B, A {
}
其中 C 类似于接口 D:
interface D {
name: string;
value: string;
sub: {
query: string[]
},
old: number;
new: boolean;
}
所以我可以有一个功能:
function merge<T, U>(t: T, u: U): interface C extends T, U {
// Merge objects
// ...
return obj;
}
它不一定是一个接口。 A 类型也可以(我认为)。
类型 A & B
不起作用,因为那时我有一个交集(例如 value
将是 number & string
类型)。
我使用这个 MergeReplace
类型来更准确地输入 Object.assign({}, T, S)
:
type MergeReplace<T, S> = Omit<T, keyof T & keyof S> & S;
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
如果您使用的是 < 2.8 的 TypeScript,Exclude
可以这样定义:
type Project<K extends string, T> = (T & {[x: string]: never})[K];
type Delete<T extends string, U extends string> = ({[P in T]: P} & {[P in U]: never});
type Exclude<T extends string, U extends string> = Project<T, Delete<T,U>>;
TypeScript playground with examples
注意 MergeReplace
是右偏的,所以如果 T
和 S
共享一个 属性 但类型不同,则 S
的类型是已选择。
查看 this TypeScript issue 了解更多信息。
我想我明白了:
type MergeRightBiased<TLeft, TRight> =
TLeft extends any[] ? TRight :
TRight extends any[] ? TRight :
TLeft extends object ?
TRight extends object ? {
// All properties of Left and Right, recursive
[P in keyof TLeft & keyof TRight]: MergeRightBiased<TLeft[P], TRight[P]>
} & {
// All properties of Left not in Right
[P in Exclude<keyof TLeft, keyof TRight>]: TLeft[P];
} & {
// All properties of Right not in Left
[P in Exclude<keyof TRight, keyof TLeft>]: TRight[P]
}
// Prefer Right
: TRight
: TRight;
感谢@Oblosys 的帮助!