简体   繁体   English

如何在打字稿中定义常量数组

[英]How to define a const array in typescript

My Code:我的代码:

const WEEKDAYS_SHORT: string[] = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']

the error message comes from TypeScript (3.0) compiler:错误消息来自 TypeScript (3.0) 编译器:

TS2322: Type 'string[]' is not assignable to type '[string, string, string, string, string, string, string]'. TS2322:类型 'string[]' 不能分配给类型 '[string, string, string, string, string, string, string]'。 Property '0' is missing in type 'string[]'.类型“string[]”中缺少属性“0”。

在此处输入图片说明

if I change the string[] to ReadonlyArray<string> , then the error message becomes:如果我将string[]更改为ReadonlyArray<string> ,则错误消息变为:

TS2322: Type 'ReadonlyArray' is not assignable to type '[string, string, string, string, string, string, string]'. TS2322:类型“ReadonlyArray”不可分配给类型“[字符串、字符串、字符串、字符串、字符串、字符串、字符串]”。 Property '0' is missing in type 'ReadonlyArray'. “ReadonlyArray”类型中缺少属性“0”。

my tsconfig.json:我的 tsconfig.json:

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es6", "dom"],
    "module": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5",
    "jsx": "react",
    "strict": true
  },
  "exclude": [
    "**/*.spec.ts",
    "node_modules",
    "vendor",
    "public"
  ],
  "compileOnSave": false
}

how can I define a readonly array in TypeScript?如何在 TypeScript 中定义只读数组?

You may add as const to your declaration; 您可以在声明中添加as const

const readonlyArray = [1, 2, 3] as const;

Furthermore the type typeof readonlyArray[number] would be 1 | 2 | 3 此外, typeof readonlyArray[number]的类型将为1 | 2 | 3 1 | 2 | 3

After debugging, I found it is not TypeScript compiler problem, it is because I used a third-party component call DayPicker: 调试后,我发现这不是TypeScript编译器问题,这是因为我使用了第三方组件调用DayPicker:

          <DayPicker
            onDayClick={this.handleDayClick}
            selectedDays={posts.day}
            months={MONTHS}
            weekdaysShort={WEEKDAYS_SHORT}
            firstDayOfWeek={1}/>

the type of the prop weekdaysShort is not string[] , but [string, string, string, string, string, string, string] 道具weekdaysShort的类型不是string[] ,而是[string, string, string, string, string, string, string]

weekdaysShort?: [string, string, string, string, string, string, string];

so TS compile says string[] doesn't match [string, string, string, string, string, string, string] . 因此TS编译会说string[][string, string, string, string, string, string, string]不匹配。

finally, I just changed the type from string[] to any to avoid this anoy error message, of course, we can change to [string, string, string, string, string, string, string] as well (too long). 最后,我只是将类型从string[]更改为any以避免出现此错误消息,当然,我们也可以更改为[string, string, string, string, string, string, string] (太长)。

As you point out the issue is cause because you try to assign the string array ( string[] ) to a 7-string-tuple. 如您所指出的,问题是由原因造成的,因为您尝试将字符串数组( string[] )分配给7字符串元组。 While your solution to use any will work it's not generally advisable to use any . 虽然您可以使用any解决方案,但通常不建议使用any Spelling out the supple is also not ideal since it's soo long. 由于太长了,拼写出柔顺也不理想。

What we can do is create a helper function to create a tuple type. 我们可以做的是创建一个辅助函数来创建一个元组类型。 This function is reusable for anywhere you need tuple: 此功能可在需要元组的任何地方重用:

function tupleArray<T extends any[]>(...v: T) {
    return v;
}
const WEEKDAYS_SHORT_INFFERED =  tupleArray('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam')  // INFFERED AS [string, string, string, string, string, string, string]
const WEEKDAYS_SHORT: [string, string, string, string, string, string, string] = WEEKDAYS_SHORT_INFFERED

I did not reproduce the issue on the TypeScript playground . 我没有在TypeScript操场上重现该问题。

But, what about using the inferred type, regardless of what it is (string array string[] or 7-string tuple [string, string, string, string, string, string, string] )? 但是,无论使用什么类型(字符串数组string[]或7字符串元组[string, string, string, string, string, string, string] ),如何使用推断的类型呢?

const WEEKDAYS_SHORT = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
const sunday = 0;
const dayShortName = WEEKDAYS_SHORT[sunday]; // => 'Dim'

Or an enum? 还是一个枚举?

enum WEEKDAYS_SHORT { 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' }
const sunday = 0;
const dayShortName = WEEKDAYS_SHORT[sunday]; // => 'Dim'

IMO, both option above are better than specifying the type any in this case. 国际海事组织,这两个选项上比指定类型更好any在这种情况下。

While the accepted answer is correct, it does have a drawback.虽然接受的答案是正确的,但它确实有一个缺点。

const readonlyArray = [1, 2, 3] as const;

let x = 4; // function parameter, etc.
// Argument of type 'number' is not assignable to parameter of type '1 | 2 | 3'.ts(2345)
// if (readonlyArray.includes(x)) {}

One alternative is to use readonly :一种替代方法是使用readonly

const readonlyArray: readonly number[] = [1, 2, 3];

let x = 4;
if (readonlyArray.includes(x)) {} // OK

// Property 'push' does not exist on type 'readonly number[]'.ts(2339)
// readonlyArray.push(4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM