簡體   English   中英

TypeScript function 只接受沒有聯合元素的元組

[英]TypeScript function which only accepts tuples without union elements

TypeScript專家!

我正在編寫一個靈活的 TypeScript function,它接受兩種類型的 arguments:class A 和 B。A 和 B 是獨立的,而不是繼承的。 但是,我需要否認使用聯合類型A | B調用的 function 的模糊用法。 A | B 有沒有辦法在TypeScript中聲明這個? 注意: function 必須是一個非常單一的 function 但不是每個用途的單獨功能。

class A {/* snip */}
class B {/* snip */}

let a:A = new A();
fn(a); // definitive usage is OK

let b:B = new B();
fn(b); // definitive usage is OK

let c:(A|B) = somecondition ? new A() : new B();
fn(c); // ambiguous usage should throw TypeScript compilation error here.

編輯:謝謝你的回答。 對不起,但上面的情況不是完全正確的情況:我需要一個 function,它接受多個 arguments 的集合,參數為 rest,如下所示:

class A {/* snip */}
class B {/* snip */}

let a:A = new A();
let b:B = new B();
let c:(A|B) = somecondition ? new A() : new B();

interface Fn {
    (...args: V[]) => void;
}

const fn: Fn = (...args) => {/* snip */};

fn(a); // single definitive usage is OK
fn(b); // single definitive usage is OK
fn(a, b, a, b); // multiple definitive usage is still OK
fn(c); // ambiguous usage should throw TypeScript compilation error here.

AB目前在結構上是相同的,因為它們只是空類。 您的真實課程可能包含某些內容。 但目前類型系統無法區分它們。

要在您的問題中描述 function,我們還需要在此處使它們不同。

class A {
  a!: string
}
class B {
  b!: string
}

您問題中的重載方法實際上是正確的解決方案。 只需刪除包含聯合的重載。

interface Fn {
    (arg: A): any;
    (arg: B): any;
}

使用此類型聲明 function 並調用它將導致以下行為:

let fn: Fn = () => {}

let a:A = new A();
fn(a); // ok

let b:B = new B();
fn(b); // ok

let c:(A|B) = (true as boolean) ? new A() : new B();
fn(c); // No overload matches this call.

操場


該編輯肯定會使事情復雜化:/

讓我們再次填補我們的班級。

class A {
  a!: number
}
class B {
  b!: string
}

現在到 function 本身:

type IsUnion<T, U extends T = T> = 
  T extends unknown ? [U] extends [T] ? {} : never : {};

type ValidateTuple<T extends any[]> = T & {
  [K in keyof T]: IsUnion<T[K]>
}

interface Fn {
    <T extends any[]>(...args: ValidateTuple<[...T]>): void;
}

const fn: Fn = (...args) => {};

function 需要有一個通用類型T來存儲...args的類型。 現在超載是不夠的。

我們可以對元組T中的元素進行 map 並檢查每個元素是否為並集。 如果它是一個聯合,我們將它相交而never導致編譯錯誤。

fn(a); // ok
fn(b); // ok
fn(a, b, a, b); // ok

fn(c); // Error

操場

你不能這樣做。

JS 不支持 function 重載。 TS 提供了這個,但在實現級別你最終只有一個 function。

您輸入的第一個參數實際上是A | B A | B 所以沒有辦法允許AB ,但不允許A | B A | B

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM