[英]TypeScript union of strings not assignable to union of tuples in 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.
A
和B
目前在結構上是相同的,因為它們只是空類。 您的真實課程可能包含某些內容。 但目前類型系統無法區分它們。
要在您的問題中描述 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
。 所以沒有辦法允許A
和B
,但不允許A | B
A | B
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.