Typescript 基于调用的方法更改类型
我有一个类,它应该允许您使用链接解析Typescript 基于调用的方法更改类型,typescript,typescript-generics,Typescript,Typescript Generics,我有一个类,它应该允许您使用链接解析缓冲区 类解析器{ 专用缓冲区:缓冲区; 专用偏移量:数字; 私人varsInternal:记录; 构造函数(缓冲区:缓冲区){ 这个偏移量=0; this.buffer=缓冲区; this.varsInternal={}; } char(名称:string):这个{ const val=this.buffer.readUInt8(this.offset); this.varsInternal[name]=val; 该偏移量+=1; 归还这个; } short
缓冲区
类解析器{
专用缓冲区:缓冲区;
专用偏移量:数字;
私人varsInternal:记录;
构造函数(缓冲区:缓冲区){
这个偏移量=0;
this.buffer=缓冲区;
this.varsInternal={};
}
char(名称:string):这个{
const val=this.buffer.readUInt8(this.offset);
this.varsInternal[name]=val;
该偏移量+=1;
归还这个;
}
short(名称:string):这个{
const val=this.buffer.readUInt16BE(this.offset);
this.varsInternal[name]=val;
该偏移量+=2;
归还这个;
}
vars():T{
将此文件退回。varsInternal;
}
}
所以你能做的是:
const data=new解析器(myBuffer)
.char(“myChar”)
.char(“其他char”)
.short(“myShort”)
.vars();
console.log(数据);//{myChar:32,otherChar:123,myShort:123544}
但我必须为此手动编写类型:
const data=new解析器(myBuffer)
.char(“myChar”)
.char(“其他char”)
.short(“myShort”)
.vars();
log(data.myChar);
//^^^^^^^不存在
const data2=新解析器(myBuffer)
.char(“myChar”)
.char(“其他char”)
.short(“myShort”)
.vars();
console.log(data.myChar);//作品
你可以看到这变得很难看
因此,我想知道是否有可能写入
char
和short
的返回值,告诉TypeScript每次我链接char
和short
时,vars
都会添加一个字段。一个可能的想法是每次添加新财产。在本例中,T
是表示整个记录
数据结构的类型
class Parser<T extends Record<string, number> = Record<string, number>> {
private buffer: Buffer;
private offset: number;
private varsInternal: T
constructor(buffer: Buffer) {
this.offset = 0;
this.buffer = buffer;
this.varsInternal = {} as T;
}
char<K extends string>(name: K): Parser<T & Record<K, number>> {
const val = this.buffer.readUInt8(this.offset); // returns number
this.varsInternal[name] = val;
this.offset += 1;
return this as Parser<T & Record<K, number>>
}
// change short method analogue to char above
vars() {
return this.varsInternal;
}
}
让我们设计一个类型别名
AddProp
,它接受一个对象类型T
、一个键类型K
、一个值类型V
,并生成一个包含T
中所有属性的新对象类型,以及一个包含键K
和值V
的新属性。这里有一种定义它的方法:
type AddProp<T, K extends PropertyKey, V> =
(T & { [P in K]: V }) extends infer O ? { [P in keyof O]: O[P] } : never;
这里我将T
的值设置为空对象类型{}
。我们希望varsInternal
的类型为T
,并且我们必须确保varsInternal
的初始值{}
与T
匹配(如果您在新解析器(缓冲区)
中手动指定T
,那么就不要这样做)
现在,让我们添加一个要重用的私有方法,该方法将向this.varsInternal添加一个键类型为
K
且值类型为V
的属性,并返回this
,其中我们断言返回的this
将是解析器的类型,我删除了我的评论,因为我可以在您的示例代码中看到number
,因为返回类型在方法上是已知的,而不是使用any
,使用Record
会更好,除了这是一个简洁的解决方案之外。@Eldar很好的回答,似乎OP希望number
在这里作为记录值类型(更新的答案)。对于char
方法,它应该是string
,对于简称方法,它应该是number
等。是的,这取决于它将如何进一步处理。对于这个解析器类的范围,number
似乎就足够了,因为所有示例值和类型都使用它。
type AddProp<T, K extends PropertyKey, V> =
(T & { [P in K]: V }) extends infer O ? { [P in keyof O]: O[P] } : never;
class Parser<T = {}> {
private buffer: Buffer;
private offset: number;
private varsInternal: T;
constructor(buffer: Buffer) {
this.offset = 0;
this.buffer = buffer;
this.varsInternal = {} as T;
}
private addProp<K extends PropertyKey, V>(prop: K, val: V): Parser<AddProp<T, K, V>> {
(this.varsInternal as any)[prop] = val;
return this as any;
}
char<K extends PropertyKey>(name: K) {
const val = this.buffer.readUInt8(this.offset);
const ret = this.addProp(name, val);
this.offset += 1;
return ret;
}
short<K extends PropertyKey>(name: K) {
const val = this.buffer.readUInt16BE(this.offset);
const ret = this.addProp(name, val);
this.offset += 2;
return ret;
}
vars(): T {
return this.varsInternal;
}
}
declare const myBuffer: Buffer;
const data = new Parser(myBuffer)
.char("myChar")
.char("otherChar")
.short("myShort")
.vars();
/* const data: {
myChar: number;
otherChar: number;
myShort: number;
}*/
console.log(data.myChar); // number