npm包csv-parse实现了一个类似API的Node.JS Stream:
const parser = parse();
parser.on('readable', () => {
let record: any; // <-- it should be string[]
while (record = parser.read()) {
output.push(record);
}
});
interface parse {
(options?: options): NodeJS.ReadWriteStream;
}
parse
的返回类型为NodeJS.ReadWriteStream
,其方法read
返回string | Buffer
。
interface ReadWriteStream extends ReadableStream, WritableStream {
// ...
}
interface ReadableStream extends EventEmitter {
read(size?: number): string | Buffer;
// ...
}
根据这个定义,我无法将变量let record: any = parser.read()
定义为其实际类型string[]
。
我试图像这样修改csv-parse的类型定义:
interface ParserStream extends NodeJS.ReadWriteStream {
read(size?: number): string[];
}
interface parse {
(options?: options): ParserStream;
}
它不起作用,因为TypeScript不允许扩展接口并更改方法的返回类型。
我能想到的是将NodeJS Stream更改为通用类型,如:
interface GenericReadableStream <T> extends EventEmitter {
read(size?: number): T
// ...
}
interface ReadableStream extends GenericReadableStream <string | Buffer> {}
然后我可以定义:
interface ParserStream extends GenericReadableStream <string[]> {}
我不知道这是不是一个好方法。它在当前的Node.JS类型定义中影响很大。
答案 0 :(得分:1)
首先,CsvParser实施使用object mode中的流,因此string | Buffer
对CsvParser.read
来说并不是一个好的返回类型。
幸运的是,TypeScript允许扩展接口并将方法的返回类型更改为any
。因此,您可以将csv-parse
类型定义更改为
interface CsvParser extends NodeJS.ReadWriteStream {
read(size?: number): any;
允许此代码编译
let record: string[];
while (record = parser.read()) {
但这不够严格,因为这也会编译:
let record: number[];
while (record = parser.read()) {
要禁止这种情况,您需要声明一个将read
返回类型更改为string[]
的接口。您无法在直接扩展ReadWriteStream
的界面中执行该操作,因为string[]
与string | Buffer
不兼容。但是,如果添加中间步骤 - 扩展ReadWriteStream
的接口并且read
的返回类型与两者兼容,则可以实现。它可以是any
的交集类型,也是我们可以使用通用参数T
的所需类型:
interface ObjectStream<T> extends NodeJS.ReadWriteStream {
read(size?: number): any & T;
}
然后你可以让CsvParser扩展它:
interface CsvParser extends ObjectStream<string[]> {
read(size?: number): string[];
}
这样,您仍然需要修改csv-parser
类型定义,但不需要更改节点流的类型定义。
注意:第一次尝试答案是
interface CsvParser extends NodeJS.ReadWriteStream {
read(size?: number): any & string[];
正如@aleung注意到的那样,与
没什么不同 interface CsvParser extends NodeJS.ReadWriteStream {
read(size?: number): any;
因为它仍然允许将读取结果分配给任何类型的变量。