有一个typeof
方法可以从一个值生成一个类型,但是它只是将值直接转换成一个类型,我想用一个对象的值来创建另一个对象的类型信息,如下所示,
type Column = Readonly<{ type: "numeric" | "text"; name: string }>;
type TypeOfColumns<T extends Column[]> = {}; // ...
const columns: Column[] = [
{ type: "numeric", name: "id" },
{ type: "text", name: "firstName" },
];
// If I wrote the following,
type ColumnType = TypeOfColumns<typeof columns>;
// I want the type to be inferred as follows,
type NeedColumnType = { id: number; firstName: string };
我以为我可以通过使用extends读取值来做到这一点,但它根本不起作用。
type Column = Readonly<{ type: "numeric" | "text"; name: string }>;
type TypeOfColumn<T extends Column> = {
[key in T["name"]]: T["type"] extends "numeric" ? number : string;
};
type TypeOfColumns<T extends Column[]> = {
[key in T[number]["name"]]: TypeOfColumn<T[number]>;
};
const columns: Column[] = [
{ type: "numeric", name: "id" },
{ type: "text", name: "firstName" },
];
type ColumnType = TypeOfColumn<typeof columns[0]>;
/* Output
type ColumnType = {
[x: string]: string;
}
*/
type ColumnsType = TypeOfColumns<typeof columns>;
/* Output
type ColumnsType = {
[x: string]: TypeOfColumn<Readonly<{
type: "numeric" | "text";
name: string;
}>>;
}
*/
1条答案
按热度按时间2vuwiymt1#
让我们从
columns
开始。列的类型当前为Column[]
。因此,在column
上使用typeof
将计算为Column[]
。您希望编译器通过删除类型注解来 * 推断 * 文本类型。这需要使用
as const
来完成,以便编译器推断文本类型而不仅仅是string
。可选地,您可以使用satisfies
readonly Column[]
来验证类型。TypeOfColumns
的约束现在必须更改为接受readonly
数组。类型内部的Map逻辑也需要更改。我们Map到T[number]
而不是T[number]["name"]
。每个联合成员K
可用于提取属性名K["name"]
和对应的类型K["type"]
。Playground