gpt4 book ai didi

javascript - TypeScript:在不显式定义键的情况下创建类型化记录

转载 作者:行者123 更新时间:2023-12-05 03:49:04 26 4
gpt4 key购买 nike

我想做的是创建一个对象,它是某个接口(interface)的记录,并让 TypeScript 能够根据我的对象中的内容推断键。我已经尝试了一些东西,但没有一个能完全满足我的要求。

interface Person {
firstName:string
}

const peopleObj = {
Jason: {
firstName: "Jason"
},
Tim: {
firstName: "Tim"
}
} as const;

console.log(peopleObj);

在这里,如果您查看 peopleObj,TypeScript 会知道确切的键,因为 as const。这里的问题是我没有强制每个对象都是 Person。所以我接下来尝试了这个:

const peopleObj: Record<string, Person> = {
Jason: {
firstName: "Jason"
},
Tim: {
firstName: "Tim"
}
} as const;

这里,由于定义了 Record,每个对象都必须是 Person,但是 TypeScript 失去了知道所有键的能力,因为现在它们只是 string 而不是常量 'Jason' | 'Tim',这就是问题的症结所在。我知道我可以明确地使用 'Jason' | 'Tim' 代替了我的 string 类型,但这在现实生活中是一个相当大的对象,每次我添加到它或从中删除时都会显式更新该类型乏味。

有没有一种方法可以两全其美,让 TypeScript 仅根据对象中的内容推断对象中的键?我找到了一种方法,虽然它不是很干净,但我觉得可能有更好的方法:

interface Person {
firstName:string
}

type PeopleType<T extends string> = Record<T, Person>;

const peopleObj: Record<string, Person> = {
Jason: {
firstName: "Jason"
},
Tim: {
firstName: "Tim"
}
} as const;

const People:Record<keyof typeof peopleObj, Person> = peopleObj;

console.log(People.Jason);

最佳答案

我相信您的第三种方法实际上不起作用 - 因为您可以毫无错误地访问 People.foo。这是因为当您将 peopleObj 构造为 Record<string, Person> 时,它的类型现在是那个。然后你做 keyof Record<string, Person> ,计算结果为字符串。

我知道实现此目的的唯一方法是使用具有泛型的函数。这允许您对输入参数应用约束,然后返回原始类型。

const createPeople = <T extends Record<string, Person>>(people: T) => people;

const myPeople = createPeople({
Jason: {
firstName: "Jason"
},
Tim: {
firstName: "Tim"
}
});

console.log(myPeople.Jason);
console.log(myPeople.foo); // error

否则你会遇到 22 条军规 - 即 - 我想强制我的 key 是 Person 类型,但我不知道我的 key 是什么。

您可能更喜欢的另一种方式 - 基本相同但没有功能:

interface Person {
firstName:string
}

// Force evaluation of type to expanded form
type EvaluateType<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

type PeopleType<T extends Record<string, Person>> = EvaluateType<{[key in keyof T]: Person }>;

const peopleLookup = {
Jason: {
firstName: "Jason"
},
Tim: {
firstName: "Tim"
}
};

const people: PeopleType<typeof peopleLookup> = peopleLookup;

console.log(people.Jason);
console.log(people.foo);

关于javascript - TypeScript:在不显式定义键的情况下创建类型化记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64119527/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com