Como exigir uma sequência específica na interface TypeScript


144

Estou criando um arquivo de definição TypeScript para uma biblioteca js de terceiros. Um dos métodos permite a um objeto opções, e uma das propriedades do objeto opções aceita uma string da lista: "collapse", "expand", "end-expand", e "none".

Eu tenho uma interface para o objeto de opções:

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

A interface pode impor isso; portanto, se você incluir um IOptionsobjeto na brace_stylepropriedade, ela permitirá apenas uma sequência que esteja na lista aceitável?


4
Por favor, revisite as respostas para esta pergunta
Andreas

Ao longo das linhas do comentário de @Andreas, por que você prefere a resposta do RyanQ ao invés de Denis Khay's ? Denis 'parece imo mais amplamente aplicável.
ruffin 19/03

Respostas:


226

Isso foi lançado na versão 1.8 como "tipos literais de string"

O que há de novo no Typecript - Tipos literais de string

Exemplo da página:

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

6
Requer copiar e colar linhas com cadeias de caracteres em qualquer lugar do aplicativo em que você precise passar cadeias desse tipo como argumento. Se você estiver sempre usando o AnimationOptions inteiro, essa solução parece boa, mas para casos de uso em que você pode apenas passar o tipo 'easing', está errado. Veja a resposta de Denis Khay, é muito melhor.
Patryk Wlaź

121

Tente isto

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

export interface IReadings {
   param:ReadingTypes
}

12
Isso deve ser marcado como correto, pois permite reutilizar o tipo criado em qualquer lugar do aplicativo.
Patryk Wlaź

Isso é exatamente o que eu estava procurando como uma maneira de passar uma matriz de seqüências de caracteres como valores para um tipo enumerado. Ignorando completamente a enum e usando type, pude passar o seguinte exemplo: const myVar: ReadingTypes = ["some"|"variants"];enquanto ainda mantinha uma sintaxe de digitação de enum dinâmica. Concordo plenamente que essa deveria ter sido a resposta marcada como correta.
Mdawsondev 30/12/19

existe uma maneira de usar isso, mas digitado suavemente assim type VisibilityTypes = VISIBILITY.PUBLISH | VISBIBILITY.DRAFT, recebo um erro de namespace não encontrado, no entanto, quando codificá-los, parece que funciona
Max Carroll

Eu encontrei um caminho e adicionei uma nova resposta
Max Carroll

10

Talvez não seja exatamente o que você queria, mas Enumparece uma solução perfeita para você.

enum BraceStyle {Collapse, Expand, EndExpand, None}

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

As enums são, no entanto, baseadas em números. Isso significa que durante o tempo de execução, um valor real para, por exemplo BraceStyle.Collapse, será 0 neste caso. Mas você pode usá-los com outros scripts, mesmo não tipográficos, pois eles são compilados em objetos. É assim que BraceStylecuidará da compilação e execução:

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

Se você desejar seqüências de caracteres, poderá usar uma classe com membros estáticos, conforme descrito aqui


enums podem ter valores de sequência (agora, pelo menos, não tenho certeza se poderiam em 2014). enum BraceStyle { Collapse = "Collapse", Expand = "Expand" }.
ZachB

Se eles pudessem em 2014, eu mencionaria isso na minha resposta.
Kuba Jagoda

8

O TS oferece uma digitação para valores de sequência específicos, chamados tipos literais de sequência .

Aqui está um exemplo de como usá-los:

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

No TypeScript 2.4 em diante, você pode usar as String Enums

Eu sou a favor dessa abordagem porque evita a necessidade de ter a mesma string codificada em mais de um local.

É possível criar um enum onde os valores são cadeias

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

Esse enum pode ser usado como um tipo em uma interface ou classe

export interface UserOptions  {
  visibility:  VISIBILITY 
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.