有两种类型
type A = {
x: number
y: number
}
type B = {
y: number
z: number
}
Run Code Online (Sandbox Code Playgroud)
如何获得具有该类型的共同属性的类型?
type C = Something<T1, T2> // { y: number }
Run Code Online (Sandbox Code Playgroud)
qiu*_*qiu 15
虽然其他答案中通常建议使用以下类型:
type Common<A, B> = {
[P in keyof A & keyof B]: A[P] | B[P];
}
Run Code Online (Sandbox Code Playgroud)
它无法检查属性值是否可以相互分配。这意味着和可能Common<A, B>具有并非真正共享的属性。AB
type A = { a: number; x: string; z: number }
type B = { b: number; x: number; z: number}
Common<A, B> // => { x: string | number; z: number}
// above should just be { z: number }, since the type of property x is not
// assignable to the type of property x in both A and B.
Run Code Online (Sandbox Code Playgroud)
这很糟糕的原因是因为将 type 的对象解构为 type或 typeCommon<A, B>
的对象对于或可能会失败。例如,ABAB
const sharedProps: Common<A, B> = { x: 'asdf', z: 9 }
const a: A = { ...sharedProps, a: 1 }
// below throws type error; string not assignable to number
const b: B = { ...sharedProps, b: 1 }
Run Code Online (Sandbox Code Playgroud)
这很令人困惑,并且对我们可以使用泛型类型执行的操作施加了任意限制。
我建议使用以下类型(适用于 TS4.1+):
/**
* Omits properties that have type `never`. Utilizes key-remapping introduced in
* TS4.1.
*
* @example
* ```ts
* type A = { x: never; y: string; }
* OmitNever<A> // => { y: string; }
* ```
*/
type OmitNever<T extends Record<string, unknown>> = {
[K in keyof T as T[K] extends never ? never : K]: T[K];
};
/**
* Constructs a Record type that only includes shared properties between `A` and
* `B`. If the value of a key is different in `A` and `B`, `SharedProperties<A,
* B>` attempts to choose a type that is assignable to the types of both values.
*
* Note that this is NOT equivalent to `A & B`.
*
* @example
* ```ts
* type A = { x: string; y: string; }
* type B = { y: string; z: string }
* type C = { y: string | number; }
*
* A & B // => { x: string; y: string; z: string; }
* SharedProperties<A, B> // => { y: string; }
* SharedProperties<B, C> // => { y: string | number; }
* ```
*/
type SharedProperties<A, B> = OmitNever<Pick<A & B, keyof A & keyof B>>;
Run Code Online (Sandbox Code Playgroud)
此类型正确返回保证是 和 的子类型的共享属性A,B因为只要不是,A & B就保证是A和 的子类型。BA & Bnever
type A = { a: number; x: string; z: number }
type B = { b: number; x: number; z: number}
SharedProperties<A, B> // => { z: number }
Run Code Online (Sandbox Code Playgroud)
kub*_*ube 13
使用静态keyof运算符:
type Ka = keyof A // 'x' | 'y'
type Kb = keyof B // 'y' | 'z'
type Kc = Ka & Kb // 'y'
Run Code Online (Sandbox Code Playgroud)
并使用以下属性定义映射类型Kc:
type C = {
[K in keyof A & keyof B]: A[K] | B[K]
}
Run Code Online (Sandbox Code Playgroud)
这定义了一种新类型,其中每个键都将出现在A和中B.
与此键关联的每个值都将具有类型A[K] | B[K],以防A[K]和B[K]不同.
仅当在A和B中键入相同时,才使用条件类型将键映射到值:
type MappedC = {
[K in keyof A & keyof B]:
A[K] extends B[K] // Basic check for simplicity here.
? K // Value becomes same as key
: never // Or `never` if check did not pass
}
Run Code Online (Sandbox Code Playgroud)
通过访问所有键,从此对象获取所有值的并集:
// `never` will not appear in the union
type Kc = MappedC[keyof A & keyof B]
Run Code Online (Sandbox Code Playgroud)
最后:
type C = {
[K in Kc]: A[K]
}
Run Code Online (Sandbox Code Playgroud)
Fab*_*uer 10
根据@kube 的回答,您可以使用泛型来创建可重用类型:
type Common<A, B> = {
[P in keyof A & keyof B]: A[P] | B[P];
}
Run Code Online (Sandbox Code Playgroud)
这允许您即时创建交叉点:
const c: Common<T1, T2> = { y: 123 };
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
823 次 |
| 最近记录: |