我很想在打字稿中創建一個記憶功能,并且應該能夠記憶的功能必須只接受簡單型別。
type ArgTypes<T> = T extends (...a: infer A) => unknown ? A : [];
type FuncWithSimpleParams = (...args: (number | string | boolean | null | undefined)[])
=> any;
export function memoize<T extends FuncWithSimpleParams>(func: T) {
const cache = {}
return function wrapper(...args: ArgTypes<T>) {
const cacheKey = args.join('.');
const cacheHit = cache.get(cacheKey);
if (cacheHit) {
return cacheHit;
}
const result = func(...args);
cache[cacheKey] = result;
return result;
};
}
但是當我像這樣使用它時
memoize(function (first: string, second: string) {
return `${first}${second}`
})
我收到打字稿錯誤說
引數“first”和“args”的型別不兼容。輸入'字串| 數量 | 布林值 | 空| undefined' 不可分配給型別 'string'。
uj5u.com熱心網友回復:
此函式型別:
type FuncWithSimpleParams = (...args: (number | string | boolean | null | undefined)[])
=> any;
宣告一個可以使用任何這些引數呼叫的函式。但是你傳遞給它一個只能接受string引數的函式。
“但是,亞歷克斯”,你是說“T extends FuncWithSimpleParams應該允許這樣做,對吧?”
嗯,不。
type Test = // This is `false`
((a: 1) => void) extends ((a: 1 | 2) => void)
? true
: false
所以函式引數不能以這種方式擴展。
你真的有錯誤的泛型。相反,您希望函式的引數作為泛型型別,因此您不必擔心擴展函式型別的復雜語意。
例如:
type SimpleType = number | string | boolean | null | undefined
type FuncWithSimpleParams<T extends SimpleType> = (...args: T[]) => any;
現在FuncWithSimpleParams有一個泛型。這意味著結果將只允許SimpleType作為引數的子集,無論是泛型引數的子集。
現在memoize變成:
export function memoize<T extends SimpleType>(func: FuncWithSimpleParams<T>) {
在這個操場上一切都按預期進行
此外,現在您ArgTypes完全擺脫了(Parameters<T>無論如何),而只是使用T[],因為您知道引數型別而無需顯式詢問函式。
export function memoize<T extends SimpleType>(func: FuncWithSimpleParams<T>) {
const cache = {}
return function wrapper(...args: T[]) { // just T[] now
const cacheKey = args.join('.');
const cacheHit = cache.get(cacheKey);
if (cacheHit) {
return cacheHit;
}
const result = func(...args);
cache[cacheKey] = result;
return result;
};
}
當你得到正確的答案時,一切似乎都變得簡單了,真是太神奇了。
這幾乎有效。我的示例應該使用不同型別的引數。如果您將“第二個”引數更改為數字。你得到我所指的錯誤
If you want to allow any number of arguments of different types, then your generic needs to be an array type, which allows it to infer the arguments as a tuple type of known length where each index has a specific type.
type SimpleType = number | string | boolean | null | undefined
type FuncWithSimpleParams<T extends SimpleType[]> = (...args: T)
=> any;
export function memoize<T extends SimpleType[]>(func: FuncWithSimpleParams<T>) {
const cache = {}
return function wrapper(...args: T) {
const cacheKey = args.join('.');
const cacheHit = cache.get(cacheKey);
if (cacheHit) {
return cacheHit;
}
const result = func(...args);
cache[cacheKey] = result;
return result;
};
}
memoize(function (first: string, second: number) {
return `${first}${second}`
})
Playground
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/317361.html
標籤:打字稿
