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 문제를 읽고 있습니다.
다음과 같은 다른 질문도 있습니다.
하지만 문제는 기존 유형 ( 예 : WebGL 객체)과 사용자 정의 클래스를 사용하는 동작의 차이 입니다.
장황 해 보이지만 단일 구현으로 벗어날 수 있습니다. 앱의 다른 부분이 구성되는 방식 때문에 나에게는 다소 유리하지 않습니다. 어딘가에서 뭔가 추악하게 보일 것입니다. 그러나 이것은 지금은 좋습니다! 감사!
아래 실제 코드.
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는 명목이 아닌 구조적입니다. 즉, 두 유형이 동일한 모양이지만 이름이 다른 경우 동일한 유형으로 간주됩니다. 그리고 불행하게도, WebGLTexture
그리고 WebGLBuffer
이 나타납니다 같은 모양을 가지고 있습니다.
VSCode 또는 typescript 플레이 그라운드에서 이러한 유형 중 하나를 cmd + 클릭 (또는 Ctrl + 클릭)하면 선언 된 방법을 볼 수 있습니다. 이 두 선언은 다음과 같습니다.
interface WebGLTexture extends WebGLObject {}
interface WebGLBuffer extends WebGLObject {}
슬프게도 두 유형은 단순히 변경되지 않은 WebGLObject
s 로 선언됩니다 . Typescript는 그들을 구분할 수 없습니다. 따라서 두 번째 함수 오버로드를 트리거하려고하면 typescript는 첫 번째 오버로드가 일치 함을 인식하고이를 사용합니다.
이 인위적인 코드에서 더 나은 솔루션을 조언하기는 어렵지만 여기서 다른 접근 방식을 원할 것입니다.
전달하는 내용을 명확하게하는 키가있는 객체를 대신 받아 들일 수 있습니까? 이렇게하면 서로 다른 오버로드와 서로 다른 인수 유형이 있습니다.
function f(_input: { texture: WebGLTexture }): Output1;
function f(_input: { buffer: WebGLBuffer }): Output2;
function f(_input: { texture?: WebGLTexture, buffer?: WebGLBuffer }): Output {
return null as any as Output;
}
const canvas = document.createElement("canvas")!;
const gl = canvas.getContext("webgl")!;
const buffer = gl.createBuffer()!;
const texture = gl.createTexture()!;
f({ texture }).type1Output; // works
f({ buffer }).type2Output; // works
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다