使用字符串文字数组作为类型
Use string literal array as type
我想使用单个数组 const fruits = ['banana', 'apple', 'orange']
作为普通数组,并作为 type
.
我应该能够做到这一点:
const x: fruits // => only accepts 'banana', 'apple' or 'orange'
并且还能够做到这一点:
@IsIn(fruits)
我试过将数组声明为<const>
,例如:
const fruits = <const>['banana', 'apple', 'orange']
type Fruits = typeof fruits[number] // this evaluates to type: "banana" | "apple" | "orange"
但是@IsIn(fruits)
会return出现以下错误:
Argument of type 'readonly ["banana", "apple", "orange"]' is not assignable to parameter of type 'any[]'.
The type 'readonly ["banana", "apple", "orange"]' is 'readonly' and cannot be assigned to the mutable type 'any[]'.ts(2345)
所以我想如果我创建两个数组,一个普通数组和一个只读数组,它应该可以工作。所以我尝试了这个:
const fruits = ['banana', 'apple', 'orange']
const fruits_readonly: <const>[...fruits]
type Fruits = typeof fruits_readonly[number]
但现在 Fruits
评估为 type: string
而不是 type: "banana" | "apple" | "orange"
。
确实 const
assertions 生成具有 readonly
个元素的对象和数组。如果您想获得 const
断言为您带来的字符串文字和元组类型的好处,同时还取消 readonly
-ing 结果,您可以编写一个辅助函数来做到这一点。我将其命名为 mutable()
:
const mutable = <T>(t: T): { -readonly [K in keyof T]: T[K] } => t
const fruits = mutable(['banana', 'apple', 'orange'] as const);
// const fruits: ["banana", "apple", "orange"]
这将深入一个层次。如果你有嵌套的 object/array 类型,你可能想要创建一个 DeepMutable
类型和 deepMutable()
辅助函数:
type DeepMutable<T> =
T extends object ? { -readonly [K in keyof T]: DeepMutable<T[K]> } : T
const deepMutable = <T>(t: T) => t as DeepMutable<T>;
上面的例子也是一样的,
const alsoFruits = deepMutable(['banana', 'apple', 'orange'] as const);
// const alsoFruits: ["banana", "apple", "orange"]
但嵌套对象的区别变得很重要:
const readonlyDeepFruits = {
yellow: ["banana", "lemon"],
red: ["cherry", "apple"],
orange: ["orange", "mango"],
green: ["lime", "watermelon"]
} as const;
/* const readonlyDeepFruits: {
readonly yellow: readonly ["banana", "lemon"];
readonly red: readonly ["cherry", "apple"];
readonly orange: readonly ["orange", "mango"];
readonly green: readonly ["lime", "watermelon"];
} */
const partiallyMutableDeepFruits = mutable(readonlyDeepFruits);
/* const partiallyMutableDeepFruits: {
yellow: readonly ["banana", "lemon"];
red: readonly ["cherry", "apple"];
orange: readonly ["orange", "mango"];
green: readonly ["lime", "watermelon"];
} */
const fullyMutableDeepFruits = deepMutable(readonlyDeepFruits);
/* const fullyMutableDeepFruits: {
yellow: ["banana", "lemon"];
red: ["cherry", "apple"];
orange: ["orange", "mango"];
green: ["lime", "watermelon"];
} */
好的,希望对您有所帮助。祝你好运!
我想使用单个数组 const fruits = ['banana', 'apple', 'orange']
作为普通数组,并作为 type
.
我应该能够做到这一点:
const x: fruits // => only accepts 'banana', 'apple' or 'orange'
并且还能够做到这一点:
@IsIn(fruits)
我试过将数组声明为<const>
,例如:
const fruits = <const>['banana', 'apple', 'orange']
type Fruits = typeof fruits[number] // this evaluates to type: "banana" | "apple" | "orange"
但是@IsIn(fruits)
会return出现以下错误:
Argument of type 'readonly ["banana", "apple", "orange"]' is not assignable to parameter of type 'any[]'.
The type 'readonly ["banana", "apple", "orange"]' is 'readonly' and cannot be assigned to the mutable type 'any[]'.ts(2345)
所以我想如果我创建两个数组,一个普通数组和一个只读数组,它应该可以工作。所以我尝试了这个:
const fruits = ['banana', 'apple', 'orange']
const fruits_readonly: <const>[...fruits]
type Fruits = typeof fruits_readonly[number]
但现在 Fruits
评估为 type: string
而不是 type: "banana" | "apple" | "orange"
。
确实 const
assertions 生成具有 readonly
个元素的对象和数组。如果您想获得 const
断言为您带来的字符串文字和元组类型的好处,同时还取消 readonly
-ing 结果,您可以编写一个辅助函数来做到这一点。我将其命名为 mutable()
:
const mutable = <T>(t: T): { -readonly [K in keyof T]: T[K] } => t
const fruits = mutable(['banana', 'apple', 'orange'] as const);
// const fruits: ["banana", "apple", "orange"]
这将深入一个层次。如果你有嵌套的 object/array 类型,你可能想要创建一个 DeepMutable
类型和 deepMutable()
辅助函数:
type DeepMutable<T> =
T extends object ? { -readonly [K in keyof T]: DeepMutable<T[K]> } : T
const deepMutable = <T>(t: T) => t as DeepMutable<T>;
上面的例子也是一样的,
const alsoFruits = deepMutable(['banana', 'apple', 'orange'] as const);
// const alsoFruits: ["banana", "apple", "orange"]
但嵌套对象的区别变得很重要:
const readonlyDeepFruits = {
yellow: ["banana", "lemon"],
red: ["cherry", "apple"],
orange: ["orange", "mango"],
green: ["lime", "watermelon"]
} as const;
/* const readonlyDeepFruits: {
readonly yellow: readonly ["banana", "lemon"];
readonly red: readonly ["cherry", "apple"];
readonly orange: readonly ["orange", "mango"];
readonly green: readonly ["lime", "watermelon"];
} */
const partiallyMutableDeepFruits = mutable(readonlyDeepFruits);
/* const partiallyMutableDeepFruits: {
yellow: readonly ["banana", "lemon"];
red: readonly ["cherry", "apple"];
orange: readonly ["orange", "mango"];
green: readonly ["lime", "watermelon"];
} */
const fullyMutableDeepFruits = deepMutable(readonlyDeepFruits);
/* const fullyMutableDeepFruits: {
yellow: ["banana", "lemon"];
red: ["cherry", "apple"];
orange: ["orange", "mango"];
green: ["lime", "watermelon"];
} */
好的,希望对您有所帮助。祝你好运!