Как превратить `readonly string []` в `string []`? - PullRequest
0 голосов
/ 20 июня 2020

У меня есть следующие настройки данных (не объявленные как enum, потому что они используются совместно с серверным кодом TypeScript и клиентским кодом, отличным от TypeScript):

import { enumType } from 'nexus';

export const TYPE_ENUM = Object.freeze({
  H: 'H',
  S: 'S',
});
export const TYPES = Object.freeze(Object.values(TYPE_ENUM));

export const MyType = enumType({
  name: 'MyType',
  members: TYPES,
});

TypeScript дает мне следующее предупреждение относительно поле members:

Type '(readonly string[])[]' is not assignable to type '(string | EnumMemberInfo)[] | Record<string, string | number | boolean | object>'.
  Type '(readonly string[])[]' is not assignable to type '(string | EnumMemberInfo)[]'.
    Type 'readonly string[]' is not assignable to type 'string | EnumMemberInfo'.
      Type 'readonly string[]' is not assignable to type 'string'.ts(2322)
enumType.d.ts(29, 3): The expected type comes from property 'members' which is declared here on type 'EnumTypeConfig<"MyType">'

Я понимаю ошибку. Невозможно поместить readonly string[] во что-то, ожидающее string[], потому что это разные типы. У меня вопрос: как лучше всего это преодолеть?

Я видел, что распаковка и воссоздание массива работают: members: [...TYPES] но это кажется неправильным.

1 Ответ

0 голосов
/ 20 июня 2020

У вас уже есть ответ: members: [...TYPES], потому что вам нужен другой изменяемый массив для функции enumType.

Вы можете почувствовать, что что-то не так. Но это не так, почему? Функция enumType ожидает изменяемый массив, это означает, что она может изменять его содержимое, например:

function enumType(v: {name: string; members: string[]): string[] {
  v.members.push('JOKER');
  return v.members;
}

export const MyType = enumType({
  name: 'MyType',
  members: TYPES as unknown as string[],
});
// You would expect MyType is ['H', 'S', 'JOKER'] but you are having an error in strict mode as you were trying to add an element to a freezed array

Если вы владеете функцией enumType и знаете, что она не меняет содержимое массива, в этом случае функция должна принимать readonly string[]

function enumType({v: {name: string; memebers: readonly string[]}) {
  ...
}

Если вы не являетесь владельцем функции: members: [...TYPES] - лучший способ.

...