想象一下我的需求的簡化版本:我將一組專案傳遞給一個函式、一個回呼以及我想從該陣列中彈出的專案數量。回呼將獲得該數量的專案。
如果彈出計數設定為1,我希望該回呼僅接收該單個專案。如果它是來自 的其他任何東西1,我希望它向回呼傳遞一個陣列。
我不確定在 TypeScript 中是否可行。我一直在玩但沒有成功。這是我想出的(并且不起作用):
function pop<T>(items: T[], cb: (item: T) => void, count: 1): void;
function pop<T>(items: T[], cb: (item: T[]) => void, count: undefined): void;
function pop<T>(items: T[], cb: (item: T[]) => void, count: number): void;
function pop<T>(
items: T[],
cb: ((item: T) => void) | ((item: T[]) => void),
count = 1,
): void {
if (count === 1) {
cb(items[0]);
} else if (count > 1) {
cb(items.slice(0, count));
} else {
cb([]);
}
}
任何人都可以啟發我這是否可能?或者我是否遺漏了什么?
uj5u.com熱心網友回復:
有可能,您只需要放松實作簽名(呼叫者看不到,他們只看到多載簽名):
function pop<T>(items: T[], cb: (item: T) => void, count?: 1): void;
function pop<T>(items: T[], cb: (items: T[]) => void, count: number): void;
function pop<T>(
items: T[],
cb: (items: T | T[]) => void,
count = 1,
): void {
if (count === 1) {
cb(items[0]);
} else if (count > 1) {
cb(items.slice(0, count));
} else {
cb([]);
}
}
游樂場鏈接
(由于默認為count是1的,我通過使將其折疊到第一過載簽名count可選當其型別是1)。
請注意,TypeScript 會假設您傳遞的任何非文字(或至少不是立即明顯的常量)意味著回呼需要一個陣列,因為型別是,而不是。因此,如果您在呼叫中逐字指定(或作為立即明顯的常量),則此多載僅適用于為專案(而不是陣列)提供回呼。numbercountnumber11
例子:
declare let items: number[];
pop(
items,
(item) => {
console.log(item); // type is `number`
},
1
);
let count = 1;
pop(
items,
(item) => {
console.log(item); // type is `number[]`, not `number`
},
count
);
游樂場鏈接
即使不是itemis的型別number[],在運行時它也會收到一個單一的number,而不是一個陣列,因為運行時代碼只知道count引數是1,而不是為什么它是1。正如 J?rg W Mittag 在評論中指出的那樣,這是因為多載在 TypeScript 中純粹是編譯時/型別檢查的事情;在運行時實際發生的唯一部分是 JavaScript 實作,它不知道靜態型別。(這與 Java 之類的語言形成對比,Java 中的多載實際上是獨立的函式,被呼叫的特定函式是在編譯時確定的,而不是運行時確定的。)
您可以通過以下幾種方式解決此問題:
- 而是定義兩個單獨的方法,
popOne和pop/popSome或類似的方法。 - 要求它
const只是一個文字或編譯時常量。
#1 是不言自明的,但是船長 yossarian 通過OnlyLiteral通用型別向我們展示了如何做 #2 :
type OnlyLiteral<N> = N extends number ? number extends N ? never : N : never;
那么第二個多載簽名是:
function pop<T>(items: T[], cb: (items: T[]) => void, count: OnlyLiteral<number>): void;
...number[]在我之前的例子中給我們的案例變成了一個編譯時錯誤:playground link
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/343874.html
