簡體   English   中英

如何定義具有重復結構的 typescript 類型?

[英]How do I define a typescript type with a repeating structure?

我有一個看起來像這樣的類型:

type Location=`${number},${number};${number},${number};...`

有沒有像Repeat<T>這樣的實用程序類型可以為我做到這一點? 像這樣:

type Location=Repeat<`${number},${number};`>

我認為沒有一種方法可以為您在變量聲明中使用的類型定義無限重復模式。

但是,function 上的類型保護可以檢查字符串是否與無限模式匹配,如下所示( 游樂場):

type MatchesPattern<Pattern extends string, Current extends string> = Current extends `` ? string : (Current extends `${Pattern}${infer Rest}` ? MatchesPattern<Pattern, Rest> : never);

type LocationPattern = `${number},${number};`;

declare function onlyAcceptsLocation<L extends string & IsLocation, IsLocation = MatchesPattern<LocationPattern, L>>(location: L): void;

onlyAcceptsLocation("12,34;56,78;"); // 👍 matches 

onlyAcceptsLocation("12,34;56,78"); // ⚠️

onlyAcceptsLocation("12'34;56,78;"); // ⚠️

onlyAcceptsLocation("1,2,3;45,67;"); // ⚠️

如果需要,您可以直接選擇類型string

type myLocation = string;
const myLocation: myLocation = "123123123";

console.log(myLocation);

否則,如果您想縮小范圍,最好將其聲明為const

const myLocation = "123123123";
console.log(myLocation);

那么您的類型將是myLocation的值

在此處輸入圖像描述

它僅適用於 TS >=4.5

可以創建獨立類型。

請看這個例子:

type Coordinates = `${number},${number};`

type MAXIMUM_ALLOWED_BOUNDARY = 50

type Last<T extends string[]> = T extends [...infer _, infer Last] ? Last : never;

type ConcatPrevious<T extends any[]> = Last<T> extends string ? `${Last<T>}${Coordinates}` : never

type Mapped<
    N extends number,
    Result extends Array<unknown> = [Coordinates],
    > =
    (Result['length'] extends N
        ? Result
        : Mapped<N, [...Result, ConcatPrevious<Result>]>
    )


// type MyLocation = 
// | `${number},${number};` 
// | `${number},${number};${number},${number};` 
// | `${number},${number};${number},${number};${number},${number};` 
// | `${number},${number};${number},${number};${number},${number};${number},${number};` 
// | `${number},${number};${number},${number};${number},${number};${number},${number};${number},${number};` 
// | ... 44 more ... 
// | `${number},${number};${number},${number};${number},${number};${number},${number};${number},${number};${number},${number}; ....

type MyLocation = Mapped<MAXIMUM_ALLOWED_BOUNDARY>[number]

const myLocation1: MyLocation = '45,56;67,68;' // ok
const myLocation2: MyLocation = '45,56;67,68;1,2;3,4;5,6;7,8;9,10;' // ok
const myLocation3: MyLocation = '45,56;67,68;1,2;3,4;5,6;7,8;9,10,' // expected error

操場

Mapped類型是一種表示while循環的實用程序類型。 它迭代直到Result的長度達到N 換句話說, Mapped<10> - 將迭代 10 次。 在純 js 中查看此示例:

const mapped = (N: number, Result: any[] = []): string => {
    if (N === Result.length) {
        return Result.join('')
    }
    
    const x = Math.random();
    const y = Math.random()
    return mapped(N, [...Result, `${x},${y};`])
}

在 js 中很難表示聯合,這就是我使用join('')原因。 我希望很清楚它是如何工作的。

如果你想將MAXIMUM_ALLOWED_BOUNDARY增加到 500,它會加熱你的 CPU,所以要小心。

您可能已經注意到,在類型腳本中不可能表示類型的遞歸模式,但可以創建足夠大的聯合。

請記住, ${number}類型有一些缺點。 您可以使用前導零的數字,如下所示:

const x: `${number}` = '01'.

有用的鏈接

  1. 在這里,您可以找到如何使用此模式創建一系列數字的示例。

  2. 在這里你可以找到引入此功能的 PR

  3. 在這里這里你可以找到我與這個模式相關的文章

您可以使用as const斷言從模板文字中獲取字符串文字類型,如下所示:

TS游樂場

const str1 = 'str1';
const str2 = `${str1},${str1};${str1},${str1}` as const; // type is "str1,str1;str1,str1"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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