fri*_*doo 6 generics typescript
我正在尝试编写一个通用函数,它接受一个array: T[]和一个选择器K并返回一个Record<T[K], T>将数组中的每个元素从其属性之一映射到其自身的函数。
例如
const input1 = [{ name: "Alice" }, { name: "Bob" }];
const output1: Record<string, { name: string }> = toRecord(input1, "name");
// { Alice: { name: "Alice" }, Bob: { name: "Bob" } }
// -----------------------------------------------------------------
enum Name {
Alice = "Alice",
Bob = "Bob"
}
const input2 = [{ name: Name.Alice }, { name: Name.Bob }];
const output2: Record<Name, { name: Name }> = toRecord(input2, "name");
// { Alice: { name: "Alice" }, Bob: { name: "Bob" } }
// -----------------------------------------------------------------
interface Person {
id: number;
name: string;
sibling?: Person;
}
const input3: Person[] = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
const output3: Record<number, Person> = toRecord(input3, "id");
// { 1: { id: 1, name: "Alice" }, 2: { id: 2, name: "Bob" } }
Run Code Online (Sandbox Code Playgroud)
我不知道如何限制选择器属性的类型,K以便T[K]具有 aRecord接受作为键的类型,即string | number | symbol。
这是我到目前为止所拥有的:
export function toRecord<T, K extends keyof T>(
array: T[],
selector: K
): Record<T[K], T> {
return array.reduce(
(acc, item) => (acc[item[selector]] = item, acc),
{} as Record<T[K], T>
)
}
Run Code Online (Sandbox Code Playgroud)
但这给了我以下错误T[K]:
Run Code Online (Sandbox Code Playgroud)Type 'T[K]' does not satisfy the constraint 'string | number | symbol'. Type 'T[keyof T]' is not assignable to type 'string | number | symbol'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'string | number | symbol'. Type 'T[string]' is not assignable to type 'string | number | symbol'. Type 'T[string]' is not assignable to type 'symbol'. Type 'T[keyof T]' is not assignable to type 'symbol'. Type 'T[K]' is not assignable to type 'symbol'. Type 'T[keyof T]' is not assignable to type 'symbol'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'symbol'. Type 'T[string]' is not assignable to type 'symbol'.(2344)
K我该如何限制T[K]呢string | number | symbol?
Ale*_*yne 12
Typescript 不知道 T 的值作为键是有效的。
类型“T[K]”不满足约束“string |” 数量 | 象征'。
这就是说 thatT可以是{ a: boolean }or { a: () => void },这意味着 thatT[K]可以是布尔值或函数,这两者都不是有效的对象属性名称。
所以我会限制T为一个仅具有允许作为键的值的对象:
function toRecord<
T extends { [K in keyof T]: string | number | symbol }, // added constraint
K extends keyof T
>(array: T[], selector: K): Record<T[K], T> {
return array.reduce((acc, item) => (acc[item[selector]] = item, acc), {} as Record<T[K], T>)
}
Run Code Online (Sandbox Code Playgroud)
听起来您有一个属性可能不符合作为密钥的资格。您仍然可以强类型化,只需知道如果属性的值是一个对象,那么它不能是键,因此必须将其过滤掉。如前所述,对象属性名称的类型是string | number | symbol。因此,让我们保留这些值,并丢弃其余的。
type RecordableKeys<T> = {
// for each key in T
[K in keyof T]:
// is the value a valid object key?
T[K] extends string | number | symbol
// Yes, return the key itself
? K
// No. Return `never`
: never
}[keyof T] // Get a union of the values that are not `never`.
interface Person {
name: string,
age: number
sibling?: Person
}
type PersonRecordableKeys = RecordableKeys<Person> // 'name' | 'age'
Run Code Online (Sandbox Code Playgroud)
使用该辅助类型后,我们可以将Tin的约束更改toRecord为:
function toRecord<
T extends { [P in RecordableKeys<T>]: string | number | symbol },
K extends RecordableKeys<T>
>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23885 次 |
| 最近记录: |