【发布时间】:2021-04-11 12:27:27
【问题描述】:
我想定义一个函数f,使得参数和返回类型是联合类型,但它们是绑定的,即当您调用f(anInputType) 时,您会得到aCorrespondingOutputType。我尝试了以下方法,它似乎适用于 TypeScript 4.1.3。
class Input1 {
type1Input: string = "I am type 1!";
}
class Input2 {
type2Input: string = "I am type 2!";
}
interface Output1 {
type1Output: string;
}
interface Output2 {
type2Output: string;
}
export type Input = Input1 | Input2;
export type Output = Output1 | Output2;
function f(_input: Input1): Output1;
function f(_input: Input2): Output2;
function f(_input: Input): Output {
return null as any as Output;
}
const input = new Input2();
const output = f(input);
output.type2Output // Compiles because the compiler can figure out that output is of type Output2
但是,在(我的)现实生活中,输入应该是 WebGL 对象。同样的事情,我将Input1 替换为WebGLTexture 和Input2 替换为WebGLBuffer,无法编译。
interface Output1 {
type1Output: string;
}
interface Output2 {
type2Output: string;
}
export type Output = Output1 | Output2;
function f(_input: WebGLTexture): Output1;
function f(_input: WebGLBuffer): Output2;
function f(_input: WebGLTexture | WebGLBuffer): Output {
return null as any as Output;
}
const canvas = document.createElement("canvas")!;
const gl = canvas.getContext("webgl")!;
const input = gl.createBuffer()!;
const output = f(input);
output.type2Output // Does not compile because the compiler thinks that output is of type Output1
我错过了什么吗?
我正在阅读这些 TypeScript 问题:
- https://github.com/Microsoft/TypeScript/issues/27131
- https://github.com/microsoft/TypeScript/issues/14107
以及这些其他问题:
- Typescript overloading functions with union types
- Typescript function overloads not working for the union type case
但令我困扰的是使用现有类型(即 WebGL 对象)与自定义类的行为之间的差异。
其实我是采用Alex的想法
它看起来很冗长,但有了它我可以摆脱一个单一的实现。由于应用程序其他部分的组织方式,这对我来说有点失败。 某事,某处,会看起来很丑。但这现在很好!谢谢!
下面的真实代码。
export type WebGLResource =
{ texture: WebGLTexture } |
{ buffer: WebGLBuffer } |
{ program: WebGLProgram } |
{ renderbuffer: WebGLRenderbuffer } |
{ framebuffer: WebGLFramebuffer };
export type ResourceMeta = TextureMeta | BufferMeta | ProgramMeta | RenderbufferMeta | FramebufferMeta;
function getMeta(<...omitted params...> resource: { texture: WebGLTexture }, required: true): TextureMeta;
function getMeta(<...omitted params...> resource: { buffer: WebGLBuffer }, required: true): BufferMeta;
function getMeta(<...omitted params...> resource: { program: WebGLProgram }, required: true): ProgramMeta;
function getMeta(<...omitted params...> resource: { renderbuffer: WebGLRenderbuffer }, required: true): RenderbufferMeta;
function getMeta(<...omitted params...> resource: { framebuffer: WebGLFramebuffer }, required: true): FramebufferMeta;
function getMeta(<...omitted params...> resource: { texture: WebGLTexture }, required: false): TextureMeta | null;
function getMeta(<...omitted params...> resource: { texture: WebGLBuffer }, required: false): BufferMeta | null;
function getMeta(<...omitted params...> resource: { buffer: WebGLProgram }, required: false): ProgramMeta | null;
function getMeta(<...omitted params...> resource: { renderbuffer: WebGLRenderbuffer }, required: false): RenderbufferMeta | null;
function getMeta(<...omitted params...> resource: { framebuffer: WebGLFramebuffer }, required: false): FramebufferMeta | null;
function getMeta(<...omitted params...> resource: WebGLResource, required: boolean): ResourceMeta | null {
...
}
【问题讨论】:
标签: typescript typescript-typings