class Car {
engine:number;
detials:{
good:'Boy'
}
}
Run Code Online (Sandbox Code Playgroud)
ModelProperty<T>当使用构造类时,它new ModelProperty<Car>('engine',22);应作为ie engine的属性Car并22具有相同的类型。enginenumber
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'
Run Code Online (Sandbox Code Playgroud)
engine V应该是指number。但是函数中的那一行do给出了错误。<Car,'engine'>而是唯一<Car>。默认情况下,其以下属性取决于参数。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]
}
}
Run Code Online (Sandbox Code Playgroud)
至于您的第二个问题重复,这是类型参数和推理工作方式的一个不幸的副作用,如果您为泛型参数指定默认值,则将使用该默认值并且不会发生推理。如果不指定 的默认值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'
Run Code Online (Sandbox Code Playgroud)
至于嵌套路径的第三个问题,类不能具有可变数量的类型参数,因此您可以选择为每个路径长度创建专用类。
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
Run Code Online (Sandbox Code Playgroud)
或者,如果您愿意,可以创建一个重载函数,该函数返回一个实例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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2033 次 |
| 最近记录: |