arrays - 如何键入 Typescript 数组以仅接受一组特定的值?

标签 arrays typescript union-types type-declaration

我正在为我无法控制的库编写类型声明文件。其中一个方法接受一个字符串数组作为参数,但这些字符串只能是非常具体的值。目前我将此参数输入为 string[] ,但我想知道是否有一种方法可以增强它以包含特定值。

示例源(我无法更改):

Fruits(filter) {
    for (let fruit of filter.fruits)
    {
        switch(fruit)
        {
            case 'Apple':
                ...do stuff
            case 'Pear':
                ...do stuff
            default:
                console.error('Invalid Fruit');
                return false;
        }
    }
    return true;
}

我当前的类型声明:
function Fruits(filter: FruitFilter): boolean;

interface FruitFilter {
    fruits: string[];
}

在我写这个问题时,我想出了一个部分解决方案,即定义有效字符串的联合类型,然后将该字段的类型设置为该联合的数组而不是字符串数组。这给了我想要的检查,但我注意到如果你输入一个无效的字符串,它会将数组中的所有字符串标记为无效,并显示错误 Type 'string' is not assignable to type 'Fruit' .有没有更好的方法来做到这一点,以便只有违规字符串被标记为无效,或者这与我将要得到的一样接近?

部分解决方案:
function Fruits(filter: FruitFilter): boolean;

type Fruit = 'Apple' | 'Pear'

interface FruitFilter {
    fruits: Fruit[];
}

最佳答案

所以,你的问题似乎是这样的:

type Fruit = "Apple" | "Pear";
interface FruitFilter {
  fruits: Fruit[];
}
declare function Fruits(filter: FruitFilter): boolean;
Fruits({ fruits: ["Apple", "Apple", "Pear"] }); // okay
Fruits({ fruits: ["Apple", "App1e", "Pear"] }); // error
// actual error: ~~~~~~~  ~~~~~~~  ~~~~~~ <-- string not assignable to Fruit
// expected error:        ~~~~~~~ <-- "App1e" not assignable to Fruit

并不是你有错误,而是错误没有正确地限制在数组的“坏”元素上。

我对为什么会发生这种情况的猜测是编译器倾向于将字符串文字扩大到 string和元组类型到数组,除非你给它提示不要这样做。因此,当它无法验证 fruits类型为 Fruit[] ,它会备份并查看您提供的内容。加宽 ["Apple", "App1e", "Pear"]string[] (忘记字符串文字和它是一个三元素元组的事实),意识到 string[]不可分配给 Fruit[] ,然后通过标记每个元素继续警告您。我做了一个简短的搜索 GitHub issues看看这是否曾经被报道过,但我还没有看到。可能值得提交一些东西。

无论如何,为了测试我的猜测,我决定更改 Fruits() 的声明如果可能的话,暗示我们想要一个字符串文字元组。请注意[目前没有方便的方法来做到这一点];现在进行暗示的方法是,呃,炼金术:
// 🧙⚗🌞🌛❓
declare function Fruits2<S extends string, T extends S[] | [S]>(arr: {
  fruits: T & { [K in keyof T]: Fruit };
}): boolean;
Fruits2({ fruits: ["Apple", "Apple", "Pear"] }); // okay
Fruits2({ fruits: ["Apple", "App1e", "Pear"] }); // error
//                          ~~~~~~~ <--string is not assignable to never

好吧,该错误的位置就是您想要的位置,尽管该消息可能仍然令人困惑。这就是编译器尝试分配 "Apple" 时发生的情况。到路口Fruit & "App1e"这是不存在的。编译器减少 Fruit & "App1e"never ...正确,但对于错误消息有用可能有点太早了。

无论如何,我不推荐这种“解决方案”,因为它要复杂得多,并且只会在错误情况下为您提供更好的错误体验。但至少这有点像是关于它为什么发生的答案,以及如何解决它的可能方向(例如,查找或提交有关它的问题)。好的,祝你好运!

Link to code

关于arrays - 如何键入 Typescript 数组以仅接受一组特定的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56329065/

相关文章:

javascript - 如何拦截特定请求

typescript - 类型断言与属性

javascript - TypeScript 中的强类型 Immutable.js 记录

python - mypy错误,Union/Optional重载, “Overloaded function signatures 1 and 2 overlap with incompatible return types”

typescript - 如何从 Typescript 中包含多种类型的命名空间中获取联合类型?

javascript - 数组中的对象显示为 [object Object]

java - 是什么导致了 java.lang.ArrayIndexOutOfBoundsException 异常?我该如何预防?

javascript - 我在将 indexOf 转换为 for 循环时遇到问题,因此我得到了错误的答案

javascript - 日期差异并使用 JS 插入同一数组

javascript - 如何将 JS 字符串数组转换为与 io-ts 的联合?