Как требовать конкретную строку в интерфейсе TypeScript


144

Я создаю файл определения TypeScript для сторонней библиотеки js. Один из методов позволяет объект параметров, и один из свойств объекта параметров принимает строку из списка: "collapse", "expand", "end-expand", и "none".

У меня есть интерфейс для объекта параметров:

interface IOptions {
  indent_size?: number;
  indent_char?: string;
  brace_style?: // "collapse" | "expand" | "end-expand" | "none"
}

Может ли интерфейс обеспечить это, поэтому, если вы включите IOptionsобъект со brace_styleсвойством, он разрешит только строку, которая находится в допустимом списке?


4
Пожалуйста, вернитесь к ответам на этот вопрос
— Андреас

Что-то вроде комментария от @Andreas, почему вы предпочитаете ответ RyanQ, а не ответ Дениса Хая ? Денис кажется более широко применимым imo.
— Руффин

Ответы:


226

Это было выпущено в версии 1.8 как «строковые литералы».

Что нового в Typescript - строковые литералы

Пример со страницы:

interface AnimationOptions {
  deltaX: number;
  deltaY: number;
  easing: "ease-in" | "ease-out" | "ease-in-out";
}

6
Это требует копирования и вставки строки со строками в любом месте приложения, в котором вам нужно будет передать строку этого типа в качестве аргумента. Если вы всегда используете все AnimationOptions, это решение кажется нормальным, но для случаев использования, когда вы можете передавать только тип «ослабление», это неверно. См. Ответ Дениса Хая, это намного лучше.
— Patryk Wlaź 01

121

Попробуй это

export type ReadingTypes = 'some'|'variants'|'of'|'strings';

export interface IReadings {
   param:ReadingTypes
}

12
Это должно быть отмечено как правильное, поскольку оно позволяет повторно использовать созданный тип в любом месте приложения.
— Patryk Wlaź 01

Это именно то, что я искал, как способ передать массив строк в качестве значений перечислимому типу. Полностью пропустив enum и используя type, я смог передать следующий пример: const myVar: ReadingTypes = ["some"|"variants"];сохраняя при этом синтаксис динамической типизации enum. Полностью согласен, что это должен был быть ответ, помеченный как правильный.
— mdawsondev

есть ли способ использовать это, но мягко напечатано, как это, type VisibilityTypes = VISIBILITY.PUBLISH | VISBIBILITY.DRAFTя получаю ошибку пространства имен, не найденную, однако, когда я жестко их кодирую, кажется, что это работает
— Макс Кэрролл,

Я нашел способ и добавил новый ответ
— Макс Кэрролл,

10

Возможно, это не совсем то, что вы хотели, но это Enumкажется идеальным решением для вас.

enum BraceStyle {Collapse, Expand, EndExpand, None}

interface IOptions {
  indent_size?: number;
  indent_char?: string;
  brace_style?: BraceStyle
}

Однако перечисления основаны на числах. Это означает, что во время выполнения реальное значение, например BraceStyle.Collapse, в этом случае будет равно 0. Но вы можете использовать их с другими, даже не машинописными сценариями, поскольку они компилируются в объекты. Вот как BraceStyleбудет выглядеть после компиляции и запуска:

{
    0: "Collapse",
    1: "Expand",
    2: "EndExpand",
    3: "None",
    Collapse: 0,
    Expand: 1,
    EndExpand: 2,
    None: 3
}

Если вместо этого вам нужны строки, вы можете использовать класс со статическими членами, как описано здесь


enums могут иметь строковые значения (по крайней мере, сейчас не уверен, могли ли они в 2014 году). enum BraceStyle { Collapse = "Collapse", Expand = "Expand" },
— ZachB

Если бы они могли в 2014 году, я бы упомянул это в своем ответе.
— Куба Ягода

8

TS предлагает типизацию определенных строковых значений, которые называются строковыми литералами .

Вот пример того, как их использовать:

type style =  "collapse" | "expand" | "end-expand" | "none";

interface IOptions {
  indent_size?: number;
  indent_char?: string;
  brace_style1?:  "collapse" | "expand" | "end-expand" | "none";
  brace_style2?:  style;
}

// Ok
let obj1: IOptions = {brace_style1: 'collapse'};

// Compile time error:
// Type '"collapsessss"' is not assignable to type '"collapse" | "expand" | "end-expand" | "none" | undefined'.
let obj2: IOptions = {brace_style1: 'collapsessss'};

1
function keysOf<T>(obj: T, key: keyof T) { return obj[key]; }
interface SomeInterface {
   a: string;
}
const instance: SomeInterface = { a: 'some value'};
let value = keysOf<SomeInterface>(instance, 'b'); // invalid
value =  keysOf<SomeInterface>(instance, 'a'); // valid

1

Начиная с TypeScript 2.4, вы можете использовать String Enums

Я предпочитаю этот подход, потому что он позволяет избежать необходимости иметь одну и ту же жестко закодированную строку более чем в одном месте.

Можно сделать перечисление, где значения являются строками

export enum VISIBILITY {
  PUBLISH = "publish",
  DRAFT = "draft"
}

Затем это перечисление можно использовать как тип интерфейса или класса.

export interface UserOptions  {
  visibility:  VISIBILITY 
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.