gpt4 book ai didi

typescript 没有重复值

转载 作者:行者123 更新时间:2023-12-01 21:54:54 25 4
gpt4 key购买 nike

有没有办法用uniq值声明类型数组,

我有一组字符串文字,如果我能说每个字符串文字只能有一个,那就太好了。

export type AllMapLibraries = 'drawing' | 'geometry' | 'places' | 'visualization';

export const getGoogleApiUrl = (apiKey: string, libraries: AllMapLibraries[]) => {
const librariesString = libraries.join(',');
const url = `https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=${librariesString}&key=${apiKey}`;
return url;
};

const url = getGoogleApiUrl('123', ['drawing', 'geometry', 'drawing']); // here should be error that drawing was already defined;

它不必只是数组。

但是我没有找到任何东西,并且认为这是不可能的。

这是playground

最佳答案

如果你真的想在类型系统中表示“没有重复元素的数组”,你最好的选择是将 generic 类型作为 constraint 。以下是我的开始方式:

type RemoveArrayRepeats<T extends readonly any[]> = {
[K in keyof T]: (
T[number] extends { [P in keyof T]: P extends K ? never : T[P] }[number]
? never
: T[K]
)
}

因此,类型 RemoveArrayRepeats 采用 tuple 类型并将其转换为自身的版本,其中任何重复的元素都被替换为 never 类型。像这样:

type TestSame = RemoveArrayRepeats<[1, 2, 3, 4, 5]>; // [1, 2, 3, 4, 5]
type TestDiff = RemoveArrayRepeats<[1, 2, 3, 2, 5]>; // [1, never, 3, never, 5]

它是如何工作的草图:给定一个元组类型 T ,它 maps over 每个类似数字的索引 K ,并将 T 的元素类型的并集(即 T[number] )与没有元素的 T 的元素类型的并集进行比较在索引 K(即 {[P in keyof T]: P extends K ? never: T[P]}[number] )处。如果它们不同,很好,不要管这个属性。如果它们相同,我们将重复...用 never 替换它。

[1,2,3,2,5] 为例:如果 K"0" ,那么我们比较 [1,2,3,2,5] 的元素的并集,即 1|2|3|5[never,2,3,2,5] 的元素,即 2|3|5 。因为它们不同,所以元组的第一个元素不是重复的,它被单独留下:1。现在我们看 K"1"。我们将 1|2|3|5[1,never,3,2,5] 的元素进行比较,它仍然是 1|2|3|5。它们是相同的,这意味着元组的第二个元素将被替换为 never。最终我们构建数组 0x10457.7


接下来我们将 [1,never,3,never,5] 函数声明为通用函数,其中 getGoogleApiUrl 参数被限制为 librariesAllMapLibraries[]:

declare const getGoogleApiUrl: <T extends AllMapLibraries[]>(
apiKey: string,
libraries: (T & RemoveArrayRepeats<T>) | []
) => string;

约束如何发生的细节有点奇怪。我选择将 RemoveArrayRepeats<T> 放在参数位置,这样 T & RemoveArrayRepeats<T> 本身就只会被约束为 T ;这样可以使有关 AllMapLibraries[] 等错误的错误消息易于理解。但是对于非常相似的行为,您可以改为执行 'drawink'

哦,T extends AllMapLibraries[] & RemoveArrayRepeats<T> 类型中的 | [] 是一个 trick,它给编译器一个提示,如果可能的话,我们想为 libraries 推断一个元组类型。没有它,编译器会将 libraries 视为类型 ["drawing", "drawing", "drawing"] ,这将完全丢失我们检测重复所需的信息。


让我们看看它是否有效:

getGoogleApiUrl('', []); // okay
getGoogleApiUrl('', ['drawing']); // okay
getGoogleApiUrl('', ['drawing', 'geometry']); // okay
getGoogleApiUrl('', ['drawing', 'geometry', 'places', 'visualization']); // okay
getGoogleApiUrl('', ['foo']); // error!
// ~~~~~
// Type '"foo"' is not assignable to type 'AllMapLibraries'


getGoogleApiUrl('123', ['drawing', 'geometry', 'drawing']); // error!
// ~~~~~~~~~ ~~~~~~~~~
// Type 'string' is not assignable to type 'undefined'

所有行为或多或少都符合预期。最后一种情况下的错误消息(如“Array<"drawing"> 不是 string”)不是您希望在完美世界中看到的。如果有受支持的 custom invalid type ,我们将使用它来定制错误消息。但是没有。

至少红色波浪线位于有意义的位置。好吧,也许您只希望其中一个 是一个错误;但这会使 undefined 变得更加复杂(例如,仅将一个元素与较低索引处的元素进行比较,但编译器不理解“较低索引”,因此我们需要一些表示,并且它会很快变得难看)。

但这是我在没有代码页的情况下最接近您的要求的方法。即使这个版本是否值得,也取决于您。无论如何,希望有所帮助;祝你好运!

Link to code

关于 typescript 没有重复值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58411739/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com