TypeScript无法推断构造函数返回类型,如何让asView返回Uint8Array?
TypeScript类型推断问题:asView函数返回类型应为Uint8Array而非unknown
问题描述
调用asView(Uint8Array, new Uint32Array)后,变量a的类型被推断为unknown,但预期应为Uint8Array。相关代码、类型声明及编译配置如下:
原实现代码
type ArrayBufferViewConstructor<T> = new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) => T; function asView<V, C extends ArrayBufferViewConstructor<V>>( TypedArray: C, v: BufferSource, byteOffset?: number, byteLength?: number, ): V{ return undefined as V } let a = asView(Uint8Array, new Uint32Array) a
生成的.d.ts文件
declare type ArrayBufferViewConstructor<T> = new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) => T; declare function asView<V, C extends ArrayBufferViewConstructor<V>>(TypedArray: C, v: BufferSource, byteOffset?: number, byteLength?: number): V; declare let a: unknown;
编译配置
{ "compilerOptions": { "strict": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictPropertyInitialization": true, "strictBindCallApply": true, "noImplicitThis": true, "noImplicitReturns": true, "alwaysStrict": true, "esModuleInterop": true, "declaration": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "target": "ES2017", "jsx": "react", "module": "ESNext", "moduleResolution": "node" } }
解决方案
问题出在原泛型定义的推断逻辑上,TypeScript无法从构造函数C反向推导V的具体类型。调整泛型约束,直接从构造函数提取实例类型即可解决:
修改后的函数实现
// 直接约束构造函数返回ArrayBufferView子类实例,用InstanceType提取实例类型 function asView<C extends new (...args: any[]) => ArrayBufferView>( TypedArray: C, v: BufferSource, byteOffset?: number, byteLength?: number, ): InstanceType<C> { // 补充实际逻辑,原示例的undefined仅为占位 return new TypedArray(v.buffer, byteOffset ?? v.byteOffset, byteLength ?? v.byteLength) as InstanceType<C>; } let a = asView(Uint8Array, new Uint32Array); // 此时a的类型被正确推断为Uint8Array
核心说明
- 简化泛型参数:只保留构造函数类型
C,约束为返回ArrayBufferView子类的构造函数。 - 用
InstanceType<C>工具类型直接获取构造函数对应的实例类型,无需额外定义V参数,让TypeScript能直接从传入的Uint8Array构造函数推断出返回类型。
对应的.d.ts声明
declare function asView<C extends new (...args: any[]) => ArrayBufferView>( TypedArray: C, v: BufferSource, byteOffset?: number, byteLength?: number, ): InstanceType<C>; declare let a: Uint8Array;
内容的提问来源于stack exchange,提问作者wener
相关产品推荐
相关产品推荐

