gpt4 book ai didi

通用 `keyof` `extends keyof` `typeof` 和其他的 Typescript 混淆

转载 作者:搜寻专家 更新时间:2023-10-30 20:43:13 36 4
gpt4 key购买 nike

class Car {
engine:number;
detials:{
good:'Boy'
}
}

ModelProperty<T>当使用 new ModelProperty<Car>('engine',22); 构建时应该作为 engineCar 的属性和 22engine 类型相同即 number .

export class ModelProperty<T, P extends keyof T, V  = T[P]> {
constructor(public name: P, public value: V) { }
fun(t: T){
let value: any = t[this.name]; // Should not be any
let valueWhyError: V = t[this.name]; //Error.. Why?
}
}
let engine2 = new ModelProperty<Car,'engine'>('engine','22'); // Gives error as '22' should be number.. working great.
let engine1 = new ModelProperty<Car,'engine'>('engine',2); // But there is repeatation 'engine', 'engine'
  1. 如果是engine V应该是 number .但是函数中的那一行 do给出错误。
  2. 构造函数不应该是<Car,'engine'>但只有<Car> .它的以下属性应该是默认的,具体取决于参数。
  3. 如何使其适用于 new ModelProperty<Car>(['details','good'],'Girl') 等嵌套属性.

最佳答案

对于第一个问题,您对 V 参数的处理方法的问题在于您为其指定了默认值,但这并不意味着 V 必须扩展 T[P],这是默认设置,您可以使用 V 的任何类型参数调用构造函数。只需在适当的地方使用 T[P],因为即使你正确地约束它(V extends T[P] = T[P])编译器它仍然不会能够正确地遵循 V 可从 T[P] 分配。

export class ModelProperty<T, P extends keyof T> {
constructor(public name: P, public value: T[P]) { }
fun(t: T){
let value = t[this.name]; // is T[P]
}
}

至于你的第二个重复问题,这是类型参数和推理工作方式的不幸副作用,如果你为泛型参数指定默认值,将使用该默认值并且不会发生推理。如果不指定 K 的默认值,则不能只指定 T 的值,还必须指定 K。简单的解决方法是使用两个函数的方法:

export class ModelProperty<T, P extends keyof T> {
constructor(public name: P, public value: T[P]) { }

static for<T>() {
return function <P extends keyof T>(name: P, value: T[P]){
new ModelProperty<T, P>(name, value);
}
}
}
const carModelCreator = ModelProperty.for<Car>();
let engine2 = carModelCreator('engine','22'); // Gives error as '22' should be number.. working great.
let engine1 = carModelCreator('engine',2); // But there is repeatation 'engine', 'engine'

至于嵌套路径的第三个问题,类不能有可变数量的类型参数,因此您可以选择为每个路径长度创建专用类。

export class ModelProperty2<T, P extends keyof T,  P2 extends keyof T[P]> {
constructor(public name: [P, P2], public value: T[P][P2]) { }

static for<T>() {
return function <P extends keyof T, P2 extends keyof T[P]>(name: [P, P2], value: T[P][P2]){
new ModelProperty2<T, P, P2>(name, value);
}
}
}
const carModelCreator = ModelProperty2.for<Car>();
let engine2 = carModelCreator(['detials', 'good'],'22'); //error
let engine2 = carModelCreator(['detials', 'good'],'Boy'); //ok

或者,如果您愿意,您可以创建一个返回实例 ModelProperty 的单个重载函数,其中唯一的类型参数是最后一个属性的值,路径是 string[]。创建实例时获得类型安全,但信息在

之后丢失
export class ModelProperty<T, V> {
constructor(public name: string[], public value: V) { }


static for<T>() {
function helper<P extends keyof T, P2 extends keyof T[P]>(name: [P, P2], value: T[P][P2])
function helper<P extends keyof T>(name: [P], value: T[P])
function helper(name: string[], value: any){
return new ModelProperty<T, any>(name, value);
}

return helper;
}
}
const carModelCreator = ModelProperty.for<Car>();
let engine1 = carModelCreator(['engine'], 22); // ok
let engine2 = carModelCreator(['detials', 'good'],'Boy'); //ok

关于通用 `keyof` `extends keyof` `typeof` 和其他的 Typescript 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49769314/

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