从类型中选择一个键值对
Pick one key-value pair from type
我有以下类型:
type Example = {
key1: number,
key2: string
}
我需要创建基于 Example
类型的类型,使其成为 key: value
对之一。当然,我正在寻找通用解决方案。这是这种类型应该 return:
type Example2 = { ... };
const a: Example2 = { key3: 'a' } // incorrect
const b: Example2 = { key1: 'a' } // incorrect
const c: Example2 = { key2: 1 } // incorrect
const d: Example2 = { key1: 1 } // correct
const e: Example2 = { key2: 'a' } // correct
const f: Example2 = { key1: 1, key2: 'a' } // incorrect
我正在尝试使用这个:
type GetOne<T> = { [P in keyof T]: T[P] };
type Example2 = GetOne<Example>;
但是 return 所有属性和示例 const f
都没有按预期工作。
我们将生成所有可能性的并集:
type Example = {
key1: number,
key2: string
}
type PickOne<T> = { [P in keyof T]: Record<P, T[P]> & Partial<Record<Exclude<keyof T, P>, undefined>> }[keyof T]
type Example2 = PickOne<Example>;
const a: Example2 = { key3: 'a' } // incorrect
const b: Example2 = { key1: 'a' } // incorrect
const c: Example2 = { key2: 1 } // incorrect
const d: Example2 = { key1: 1 } // correct
const e: Example2 = { key2: 'a' } // correct
const f: Example2 = { key1: 1, key2: 'a' } // incorrect
我们这样做的方式是,我们首先为每个键创建一个新类型,我们有一个对象 属性,只有那个键(暂时忽略 & Partial<Record<Exclude<keyof T, P>, undefined>>
)。所以 { [P in keyof T]: Record<P, T[P]> }
例如将是 :
type Example2 = {
key1: Record<"key1", number>;
key2: Record<"key2", string>;
}
然后使用索引运算 [keyof T]
得到这个新类型中所有值的并集,所以我们得到 Record<"key1", number> | Record<"key2", string>
此类型适用于除最后一个测试之外的所有类型,在该测试中您不希望原始类型具有多个属性。由于 excess 属性 检查与联合类型 () 一起工作的方式,如果它存在于任何联合成分中,它将允许一个键。
为了解决这个问题,我们将 Record<P, T[P]>
与一个可选地包含其余属性 (Exclude<keyof T, P>
) 的类型相交,但强制所有属性都为 undefined
.
也可以通过下面的代码实现:
export type PickOne<T> = {
[P in keyof T]?: Record<P, T[P]>
}[keyof T]
type Example = {
key1: number;
key2: string;
}
type Example2 = PickOne<Example>;
const a: Example2 = { key1: 1 } // correct
const b: Example2 = { key1: "1" } // incorrect - string cannot be assigned to number
const c: Example2 = { key2: 'a' } // correct
const d: Example2 = { key3: 'a' } // incorrect - unknown property
我有以下类型:
type Example = {
key1: number,
key2: string
}
我需要创建基于 Example
类型的类型,使其成为 key: value
对之一。当然,我正在寻找通用解决方案。这是这种类型应该 return:
type Example2 = { ... };
const a: Example2 = { key3: 'a' } // incorrect
const b: Example2 = { key1: 'a' } // incorrect
const c: Example2 = { key2: 1 } // incorrect
const d: Example2 = { key1: 1 } // correct
const e: Example2 = { key2: 'a' } // correct
const f: Example2 = { key1: 1, key2: 'a' } // incorrect
我正在尝试使用这个:
type GetOne<T> = { [P in keyof T]: T[P] };
type Example2 = GetOne<Example>;
但是 return 所有属性和示例 const f
都没有按预期工作。
我们将生成所有可能性的并集:
type Example = {
key1: number,
key2: string
}
type PickOne<T> = { [P in keyof T]: Record<P, T[P]> & Partial<Record<Exclude<keyof T, P>, undefined>> }[keyof T]
type Example2 = PickOne<Example>;
const a: Example2 = { key3: 'a' } // incorrect
const b: Example2 = { key1: 'a' } // incorrect
const c: Example2 = { key2: 1 } // incorrect
const d: Example2 = { key1: 1 } // correct
const e: Example2 = { key2: 'a' } // correct
const f: Example2 = { key1: 1, key2: 'a' } // incorrect
我们这样做的方式是,我们首先为每个键创建一个新类型,我们有一个对象 属性,只有那个键(暂时忽略 & Partial<Record<Exclude<keyof T, P>, undefined>>
)。所以 { [P in keyof T]: Record<P, T[P]> }
例如将是 :
type Example2 = {
key1: Record<"key1", number>;
key2: Record<"key2", string>;
}
然后使用索引运算 [keyof T]
得到这个新类型中所有值的并集,所以我们得到 Record<"key1", number> | Record<"key2", string>
此类型适用于除最后一个测试之外的所有类型,在该测试中您不希望原始类型具有多个属性。由于 excess 属性 检查与联合类型 (
为了解决这个问题,我们将 Record<P, T[P]>
与一个可选地包含其余属性 (Exclude<keyof T, P>
) 的类型相交,但强制所有属性都为 undefined
.
也可以通过下面的代码实现:
export type PickOne<T> = {
[P in keyof T]?: Record<P, T[P]>
}[keyof T]
type Example = {
key1: number;
key2: string;
}
type Example2 = PickOne<Example>;
const a: Example2 = { key1: 1 } // correct
const b: Example2 = { key1: "1" } // incorrect - string cannot be assigned to number
const c: Example2 = { key2: 'a' } // correct
const d: Example2 = { key3: 'a' } // incorrect - unknown property