【发布时间】:2023-03-11 02:26:01
【问题描述】:
This playground example 描述了我正在尝试做的事情,但实际上我试图将一个对象的可能键限制为另一个对象的值。
这可能吗?
【问题讨论】:
标签: typescript
This playground example 描述了我正在尝试做的事情,但实际上我试图将一个对象的可能键限制为另一个对象的值。
这可能吗?
【问题讨论】:
标签: typescript
我能得到的最接近的是这个
type accessor = "surname" | "firstname"
interface IData {
title: string;
accessor: accessor;
}
type ICell = Record<accessor, string>
【讨论】:
accessor的值是在运行时任意给定的?我认为您不能以此为基础。 TypeScript 只能作用于编译时信息(因为它只在编译期间有效)
在 TypeScript 中无法根据运行时值定义类型,因为所有类型在运行时都会被删除。你所要求的完全是不可能的。
考虑:如果这个对象是从一个返回随机值的网络服务器获取的呢?编译将如何工作?您需要连接到互联网吗?由于没有运行时类型检查,它根本不起作用。
如您所愿,要在运行时完成此操作,您可以使用普通的 javascript。例如:
const accessors = data.map(o => o.accessor);
for (const cell of cells) {
for (const key in cell) {
if (!accessors.includes(key)) {
// throw a runtime error
throw new Error("This key is not a valid accessor!");
}
}
}
【讨论】:
如果您在编译时知道IData 的类型,您可以有点这样做。所以你需要一些类似的东西:
const data = [
{
title: "First name",
accessor: "firstname",
},
{
title: "Last name",
accessor: "surname",
}
] as const
type Accessors = typeof data[number]["accessor"]
type ICell = Record<Accessors, string>
const cells: ICell[] = [
{
firstname: "Davy",
surname: "James"
},
{
firstname: "Billy",
surname: "Cricket"
}
]
如果您在编译时不知道data 的结构,就像其他答案指出的那样,您不能这样做。此外(与任何其他对象一样)您必须检查在运行时创建的任何其他数据是否符合 ICell 数据类型,如果您正在尝试这样做,您实际上无法在运行时检查它。
【讨论】: