打字稿:是否可以确保键和内部值是相同的字符串?
Typescript: Is it possible to ensure the key and an inner value are the same string?
我有一个可能变大的数据记录。我想知道是否可以强制 Record 的键与内部名称值相同?
interface Person<T> {
name: T
title: string
description: string
}
type People = Record<string, Person<string>>
// example data
const data: People = {
sarah: {
name: 'sarah',
title: 'Sarah',
description: 'Hello',
}
}
const badData: People = {
adam: {
name: 'john', // This would cause a typescript error ideally.
...
}
}
我已经尝试使用泛型设置 People,但它需要我将所有键添加到一个我宁愿避免的联合类型。 keyof
不起作用,因为对象未在需要 keyof
的地方定义。
type People<T> = Record<T, Person<T>>
const people: People<keyof typeof people> = {} // Block-scoped variable 'people' used before its declaration.ts(2448)
为此,您需要使用额外的功能。
interface Person<T> {
name: T
title: string
description: string
}
type People = Record<string, Person<string>>
type Validate<T extends People> = {
[Name in keyof T]: Name extends T[Name]['name'] ? T[Name] : T[Name] & { name: never }
}
const validator = <
Name extends string,
Human extends Person<Name>,
Data extends Record<Name, Human>
>(data: Validate<Data>) => data
const result = validator({
sarah: {
name: 'sarah',
title: 'Sarah',
description: 'Hello',
},
adam: {
name: 'john', // Error.
title: 'Sarah',
description: 'Hello',
}
})
Validate
遍历每个对象 key
/Name
并检查顶级名称是否等于 Object[Name]['name']
。如果是 - return 相同的嵌套对象。如果否 - return 相同的嵌套对象但具有 ivriden name
proeprty never
.
因此,您在应该修复的地方遇到错误。
如果你对函数参数的类型推断感兴趣,你可以查看我的 article
我有一个可能变大的数据记录。我想知道是否可以强制 Record 的键与内部名称值相同?
interface Person<T> {
name: T
title: string
description: string
}
type People = Record<string, Person<string>>
// example data
const data: People = {
sarah: {
name: 'sarah',
title: 'Sarah',
description: 'Hello',
}
}
const badData: People = {
adam: {
name: 'john', // This would cause a typescript error ideally.
...
}
}
我已经尝试使用泛型设置 People,但它需要我将所有键添加到一个我宁愿避免的联合类型。 keyof
不起作用,因为对象未在需要 keyof
的地方定义。
type People<T> = Record<T, Person<T>>
const people: People<keyof typeof people> = {} // Block-scoped variable 'people' used before its declaration.ts(2448)
为此,您需要使用额外的功能。
interface Person<T> {
name: T
title: string
description: string
}
type People = Record<string, Person<string>>
type Validate<T extends People> = {
[Name in keyof T]: Name extends T[Name]['name'] ? T[Name] : T[Name] & { name: never }
}
const validator = <
Name extends string,
Human extends Person<Name>,
Data extends Record<Name, Human>
>(data: Validate<Data>) => data
const result = validator({
sarah: {
name: 'sarah',
title: 'Sarah',
description: 'Hello',
},
adam: {
name: 'john', // Error.
title: 'Sarah',
description: 'Hello',
}
})
Validate
遍历每个对象 key
/Name
并检查顶级名称是否等于 Object[Name]['name']
。如果是 - return 相同的嵌套对象。如果否 - return 相同的嵌套对象但具有 ivriden name
proeprty never
.
因此,您在应该修复的地方遇到错误。
如果你对函数参数的类型推断感兴趣,你可以查看我的 article