javascript - 如果值在打字稿数组中,则分配新的字符串值
问题描述
如果不确定新值是否存在于有效字符串类型的数组中,如何为 Typescript 中的类型化字符串分配新值?例如
const fruits = ['apple', 'banana', 'orange'] as const;
type Fruit = typeof fruits[number];
export default function () {
let selectedFruit: Fruit = 'apple';
const url = new URL(window.location.href);
const fruitParam = url.searchParams.get('fruit'); // type is string | null
if (fruits.some((fruit) => fruitParam === fruit)) {
selectedFruit = fruitParam; // Typescript error: Type 'string | null' is not assignable to type '"apple" | "banana" | "orange"'
}
return selectedFruit;
}
检查不应该fruits.some((fruit) => fruitParam === fruit))
确保fruitParam
确实是有效的水果类型吗?TS 编译器是否无法从该检查中推断?我也试过fruits.includes(fruit)
和其他人没有任何运气。当然,明确列出类型fruitParam === 'apple' || fruitParam === 'banana' || fruitParam === 'orange'
确实有效,但并不理想。
解决方案
您需要处理类型兼容性。
selectedFruit
可以是'apple', 'banana', 'orange'
randomFruit
你的情况之一,我只是一个字符串
所以,联合类型不能被扩展string
,但 string
类型可以被扩展'apple', 'banana', 'orange'
。
因此,如果你写:
let randomFruit = getRandomFruit();
if (fruits.some((fruit) => randomFruit === fruit)) {
randomFruit = selectedFruit // no error
selectedFruit = randomFruit; // Typescript error: Type 'string' is not assignable to type '"apple" | "banana" | "orange"'
}
它会起作用的。
所以,让我们回到你的问题。
为了更清楚,让我们as const
添加basket
const basket = ['apple', 'banana', 'orange', 'lychee', 'pear', 'grapefruit'] as const;
现在,您有类似但更容易理解的错误消息:
Type '"apple" | "banana" | "orange" | "lychee" | "pear" | "grapefruit"' is not assignable to type '"apple" | "banana" | "orange"'
为了让它工作,你应该在fruits
数组中定义所有可能的水果。你的篮子应该只允许fruits
阵列中存在的水果 - 对我来说它确实有意义。
例子:
const fruits = ['apple', 'banana', 'orange', 'lychee', 'pear', 'grapefruit'] as const;
type Fruit = typeof fruits[number];
const basket = ['apple', 'banana', 'orange'] as const;
const getRandomFruit = () => basket[Math.floor(Math.random() * basket.length)];
export default function () {
let selectedFruit: Fruit = 'apple';
const randomFruit = getRandomFruit();
if (fruits.some((fruit) => randomFruit === fruit)) {
selectedFruit = randomFruit; // no error
}
return selectedFruit;
}
更新
在这里,您有一个带有 typeguard 的解决方案:
const fruits = ['apple', 'banana', 'orange'] as const;
type Fruit = typeof fruits[number];
/**
* You should yo use typeguard instead of simple condition
*/
const isAllowedFruit = (fruit: string | null): fruit is Fruit => typeof fruit === 'string' ? fruits.includes(fruit as Fruit) : false
export default function () {
let selectedFruit: Fruit = 'apple';
const url = new URL(window.location.href);
const fruitParam = url.searchParams.get('fruit'); // type is string | null
if (isAllowedFruit(fruitParam)) {
selectedFruit = fruitParam; // ok
}
return selectedFruit;
}
在这里您可以阅读有关类型保护的更多信息
推荐阅读
- python - 实例属性的 Python NotImplementedError
- amazon-web-services - lambda 实例的通信选项?
- sql - 如何从生日列中找到最低年龄,但只选择比最低年龄大 3 岁的人
- r - 遍历 NetLogo 中的两个列表:大图上下文:R 扩展。将补丁值分配给 R 中的特定补丁
- python - python classmethod可以更改实例变量的值,反之亦然?
- dask - 如何检索 Dask-YARN 作业的工作日志?
- php - 如何将选择选项更改为单选按钮并将值传递给模型
- java - 选择 Spinner 值后元素间歇性无法识别
- haxe - 将 haxe.Int64 转换为浮点数?
- c# - 当有两个 watch 实例时,StopWatch 返回 0ms