打字稿:是否可以确保键和内部值是相同的字符串?

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',
    }
})

Playground

Validate 遍历每个对象 key/Name 并检查顶级名称是否等于 Object[Name]['name']。如果是 - return 相同的嵌套对象。如果否 - return 相同的嵌套对象但具有 ivriden name proeprty never.

因此,您在应该修复的地方遇到错误。

如果你对函数参数的类型推断感兴趣,你可以查看我的 article