typescript - Typescript KeyOf - 数组或对象 - 绝望
问题描述
我有以下课程......
export class Person<T, C = T> {
lens: any = null;
private value: T;
constructor(value: T, newLens?: any) {
this.value = value;
this.lens = newLens;
}
at<K extends keyof C>(path: keyof C): Person<T, C[K]> {
if(!this.lens) {
return new Person<T, C[K]>(this.value, Lens.lens(path));
}
return new Person<T, C[K]>(this.value, Lens.compose(this.lens)(Lens.lens(path)));
}
get(): any {
if(!this.lens) return this.value;
return Lens.get(this.lens)(this.value);
}
set(f: (newValue: any) => any): T {
return Lens.set(this.lens)(f(this.get()))(this.value);
}
}
我的问题是,当我尝试在对象上使用我的新 Person 类时,我得到了不正确的行为.....
const TestPerson = {
name: {
name: "steve"
},
siblings: [{name: "shanon"}]
age: Infinity
}
const test = new Person(TestPerson).at("name").at("name") // works....
const test2 = new Person(TestPerson).at("siblings").at(0) // fails
const test3 = new Person(TestPerson).at(siblings").at("0") // still fails.
const test4 = new Person(TestPerson).at("nonexistantproperty") //correctly fails.
我的问题是我需要一个可以处理 keyof 对象和 keyof 数组的“AT”函数,但似乎无论我如何重做它我都无法实现这一点。
对我来说,这似乎是打字稿的一个巨大缺陷,数组和对象都只是引擎盖下的对象,因此对象类型上的 keyof 和数组类型上的 keyof 应该以相同的方式工作。
解决方案
最简单的解决方案是等到 typescript 2.9(在撰写本文时在RC中,应该很快就会发布)。在 2.9 之前keyof
只返回字符串索引,在 2.9 中这将包括数字和符号键。见公关。在 2.9 中,您的代码将按预期工作而无需任何更改。
在 2.8 中你可以使用条件类型来达到类似的效果
type CReturn<C, K extends keyof C> = C extends Array<any> ? C[number] : C[K];
export class Person<T, C = T> {
lens: any = null;
private value: T;
constructor(value: T, newLens?: any) {
this.value = value;
this.lens = newLens;
}
at<K extends keyof C>(path: C extends Array<any> ? number : K): Person<T, CReturn<C, K>> {
if(!this.lens) {
return new Person<T, CReturn<C, K>>(this.value, Lens.lens(path));
}
return new Person<T, CReturn<C, K>>(this.value, Lens.compose(this.lens)(Lens.lens(path)));
}
}
const TestPerson = {
name: {
name: "steve"
},
siblings: [{ name: "shanon" }],
age: Infinity
}
const test = new Person(TestPerson).at("name").at("name") // works....
const test2 = new Person(TestPerson).at("siblings").at(0) // ok
const test21 = new Person(TestPerson).at("siblings").at(0).at("name") //ok
const test4 = new Person(TestPerson).at("nonexistantproperty") //correctly fails.
推荐阅读
- inno-setup - 使用 Inno Setup 创建的更新程序不会更改应用程序版本
- python - Pandas 数据框将整列乘以另一列中的单个单元格,以控制组标识符
- javascript - setState 映射函数中对象的一种状态
- excel - 在工作表中的灵活区域上分隔宏
- url - 如何在控制器 CakePHP 中使用 $this->Html->url?
- css - Angular Material design 复选框黑色前景色(符号颜色)
- java - Couchbase 中不区分大小写的文档 ID 匹配
- sql - 插入查询以同时具有选择和值作为值
- reactjs - 根据所选应用更改外部共享消息
- elasticsearch - Elasticsearch 可以做反向前缀搜索吗?