簡體   English   中英

是否可以在 TypeScript 中使用一個沒有“任何”的參數來定義代表 function 的類型?

[英]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 接受任何類型的單個參數,那為什么不呢?

第二個更合理, fjc已經在評論中提出:

為什么不使用這樣的泛型: 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被鍵入為可變數組,所以編譯器不知道給定成員中inputtransformx和返回類型是什么,只知道它應該是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.

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