【发布时间】:2021-06-08 09:54:04
【问题描述】:
我知道您可能会很棘手,将传入字典中的 已知属性 转换为文字值。例如,对于带有“id”的字典,我们可以这样做:
function idLiteral<
T extends { id: I },
I extends PropertyKey
>(o: T): T & { id: T["id"] } {
return { ...o, id: o.id };
}
// usage
const test = idLiteral({id: "abc", name: "Bobs your uncle" });
在这种情况下,name 将是 string 类型,但 id 将被分配为文字类型 abc。当然,在对象是静态的情况下,我们可以使用 Typescript as const 运算符将对象转换为狭义的文字类型,但我想知道我们是否可以使用通过函数传递的非静态字典来做到这一点。
我尝试过这样做:
function literalValues<T extends object>(obj: T): T extends { [K in keyof T]: Readonly<infer V> }[keyof T]
? { [K in keyof T]: Readonly<V> }
: never {
return obj;
}
// usage
const narrow = literalValues({foo: 1, bar: true});
希望narrow 变量会输出为{ foo: 1; bar: true }。遗憾的是,这并没有发生,而是出现了扩大的 { foo: number; bar: boolean } 类型。
然后我将注意力转向查看第一个函数——idLiteral——是否可能是可以泛化的东西,以便我通过迭代它来构建对象类型。我想出了这个:
export const literal = <T extends object, P extends keyof T>(obj: T) => (prop: P): T & { [P]: T[P] } => {
return { ...obj, [prop]: obj[prop] };
};
const l = literal({ foo: 1, bar: true })("foo");
但此语法失败,因为P 不能用作对象的键。
这在 Typescript 中是可行的,还是我只是在浪费时间?感觉如此接近,但同时又如此遥远。
【问题讨论】:
标签: typescript typescript-typings typescript-generics