如何返回与调用函数相同的类型?



我正在编写一个函数(节点.js应用程序中的打字稿),该函数对类似数组的数据执行类似解析的过程(它需要slice()length和索引运算符[])。

我已经定义了一个可以是任何所需类型的type,以及一个标记数组/缓冲区中第一个元素的分隔符。

这一切都有效,但是一旦函数返回,它就需要转换回原始类型,理想情况下我不想执行转换,我希望函数返回与buffer参数相同的类型,同时保持所有相同的打字稿检查在函数中输入类型范围。

export type BufferLike<T> = Buffer | string | T[];
export function Parse<T>(buffer: BufferLike<T>, delim: typeof buffer[0]) {
let result: typeof buffer[] = [];
let idx = 0, i = 0;
// content not material...
result.push(buffer.slice(buffer[i] == delim ? idx : i));
return result;
}

使用中...

// creates error
// Type 'BufferLike<string>[]' is not assignable to type 'string[]'.ts(2322)
const v1: string[] = Parse("121212", "2");
// compiles
const v2: string[] = <string[]>Parse("121212", "2");

我尝试了自定义interface,但结果几乎与上述相同。

export interface Splittable<T> {
slice(idx: number, len?: number) : Splittable<T> // return same type as the class/interface
//slice(idx: number, len?: number) : T[]
[idx: number] : T // element access
readonly length: number
}

我如何定义Parse的函数签名,以便我可以让返回类型与客户端提供的参数相同,并且仍然保持类型检查?

我认为您希望使用多态this作为Splittable<T>splice()的返回类型:

export interface Splittable<T> {
slice(idx: number, len?: number): this;
[idx: number]: T
readonly length: number
}

这就是说,在类型为Splittable<T>子类型的对象上调用slice()将返回相同子类型的对象。

然后,您希望ParseS中是通用的,您获得的Splittable<T>的特定子类型以及分隔符的T

export function Parse<S extends Splittable<T>, T>(buffer: S, delim: T) {
let result: S[] = [];
let idx = 0, i = 0;
result.push(buffer.slice(buffer[i] == delim ? idx : i));
return result;
}

如果需要,也可以消除T

export function Parse<S extends Splittable<any>>(buffer: S, delim: S[number]) { ... }

无论哪种方式,您都应该获得所需的行为:

const v1: string[] = Parse("121212", "2");
const v2: boolean[][] = Parse([true, false, true], true);
const v3: Buffer[] = Parse(new Buffer(""), 123)

操场链接到代码

最新更新