[英]Is it possible to define a type representing a function with one parameter without 'any' in TypeScript?
顯然,使用any
關鍵字這是相當簡單的:
type SingleParamFunction = (arg: any) => any;
const foo: SingleParamFunction = (x: number): number => x + 1;
我嘗試了以下方法:
type SingleParamFunction = (arg: unknown) => unknown;
const foo: SingleParamFunction = (x: number): number => x + 1;
但是,編譯器抱怨“未知”不能分配給“數字”類型。
我很好奇是否可以在不訴諸any
方法的情況下這樣做,也許是使用 generics 的解決方案。
一個潛在的用例可能如下所示:
interface Foo<I, O> {
input: I;
transform: (x: I) => O;
}
const foos: Foo<any, any>[] = [
{
input: 1,
transform: (x: number) => x + 1,
},
{
input: 'hello',
transform: (s: string) => s + ' world',
},
];
for (const foo of foos) {
console.log(foo.transform(foo.input));
}
您的問題有幾種解決方案同樣有效,但會逐漸增強類型安全性。
第一個是您提出的瑣碎案例: (x: any) => any
。 盡管有“從不使用任何”的經驗法則,但判斷性使用any
可能是一個有效的選擇。 如果您只需要告訴編譯器 function 接受任何類型的單個參數,那為什么不呢?
為什么不使用這樣的泛型: type SingleParamFunction = (arg: T) => T; const foo: SingleParamFunction = (x) => x + 1;?
這解決了逆變問題,但編譯器會抱怨transform
方法的簽名,因為聯合將被傳遞,因此x
和返回類型將被推斷為聯合(例如, string | number
):
interface Foo<I> {
input: I;
transform: SingleParamFunction<I>;
}
const foos: Foo<string | number>[] = [
{
input: 1,
transform: (x) => x + 1, //Type 'string' is not assignable to type 'number'.(2322)
},
{
input: 'hello',
transform: (s: string) => s + ' world', //Type 'string | number' is not assignable to type 'string'.
},
];
for (const foo of foos) {
console.log(foo.transform(foo.input));
}
然而,這不是解決方案的問題。 因為foos
被鍵入為可變數組,所以編譯器不知道給定成員中input
或transform
的x
和返回類型是什么,只知道它應該是string | number
string | number
。
但是,如果刪除類型注釋,您將看到數組的類型被正確推斷。 這應該會給您提示您需要檢查的內容,並引導我們找到第三種解決方案:
({
input: number;
transform: (x: number) => number;
} | {
input: string;
transform: (s: string) => string;
})[]
那么,你會怎么做呢? 映射類型來救援! 您需要定義一個“Foo 的數組,其中對於可能的input
類型中的每種類型,可能有一個成員是這種類型的Foo
”。 以下是這種類型的外觀(借助鍵重新映射):
type validator<I> = Array<{ [T in I as number]: Foo<T> }[number]>;
瞧:
//all ok, valid assignment
const bars: validator<string | number> = [
{
input: 1,
transform: (x: number) => x + 1
},
{
input: 'hello',
transform: (s: string) => s + ' world'
},
];
const invalid : validator<string|number> = [
{
input: "nope", //Type 'string' is not assignable to type 'number'.(2322)
transform: (x: number) => x + 1
},
{
input: 'hello',
transform: (s: string) => Infinity //Type 'number' is not assignable to type 'string'.(2322)
},
];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.