Як потрібна певна рядок в інтерфейсі 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 над Денісом Хаєм ? Денис здається більш широко застосовною.
— ruffin

Відповіді:


226

Це було випущено у версії 1.8 як "рядкові буквальні типи"

Що нового в Typescript - рядкові літеральні типи

Приклад зі сторінки:

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

6
Для цього потрібно копіювати та вставляти рядок із рядками, де б у програмі вам не було потрібно передавати рядок такого типу як аргумент. Якщо ви завжди використовуєте цілі програми AnimationOptions, це рішення здається нормальним, але для випадків використання, коли ви можете передавати лише тип "полегшення", це неправильно. Дивіться відповідь Дениса Хая, це набагато краще.
— Patryk Wlaź

121

Спробуйте це

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

export interface IReadings {
   param:ReadingTypes
}

12
Це слід позначити як правильне, оскільки воно дозволяє повторно використовувати створений тип у будь-якому місці програми.
— Патрик Влас

Саме це я шукав як спосіб передати масив рядків як значення переліченому типу. Пропустивши повністю перелік і використовуючи type, я зміг передати наступний приклад: const myVar: ReadingTypes = ["some"|"variants"];зберігаючи синтаксис динамічного переписування. Повністю погодився, що відповідь мала бути правильною.
— 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 пропонує набір тексту на конкретні рядкові значення, які називаються рядковими типами String .

Ось приклад того, як ними користуватися:

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.