Cómo requerir una cadena específica en la interfaz TypeScript


144

Estoy creando un archivo de definición de TypeScript para una biblioteca js de terceros. Uno de los métodos de un objeto permite opciones, y una de las propiedades del objeto opciones acepta una cadena de la lista: "collapse", "expand", "end-expand", y "none".

Tengo una interfaz para el objeto de opciones:

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

¿Puede la interfaz aplicar esto, por lo que si incluye un IOptionsobjeto con la brace_stylepropiedad, solo permitirá una cadena que esté en la lista aceptable?


44
Vuelva a visitar las respuestas a esta pregunta
— Andreas

Un poco en la línea del comentario de @Andreas, ¿por qué prefieres la respuesta de RyanQ sobre la de Denis Khay's ? Denis 'parece más ampliamente aplicable imo.
— ruffin

Respuestas:


226

Esto fue lanzado en la versión 1.8 como "tipos literales de cadena"

Novedades de Typecript: tipos literales de cadena

Ejemplo de la página:

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

66
Requiere copiar y pegar una línea con cadenas donde sea que en la aplicación necesite pasar cadenas de este tipo como argumento. Si siempre está usando AnimationOptions enteros, esa solución parece estar bien, pero para los casos de uso en los que solo puede pasar el tipo de 'facilitación', está mal. Ver la respuesta de Denis Khay, es mucho mejor.
— Patryk Wlaź

121

Prueba esto

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

export interface IReadings {
   param:ReadingTypes
}

12
Esto debe marcarse como correcto, ya que permite reutilizar el tipo creado en cualquier lugar de una aplicación.
— Patryk Wlaź

Esto es exactamente lo que estaba buscando como una forma de pasar una matriz de cadenas como valores a un tipo enumerado. Al omitir completamente la enumeración y usarla type, pude pasar el siguiente ejemplo: const myVar: ReadingTypes = ["some"|"variants"];mientras mantenía una sintaxis de escritura dinámica de enumeración. Completamente de acuerdo en que esta debería haber sido la respuesta marcada como correcta.
— mdawsondev

¿hay alguna manera de usar esto pero con un tipeo suave como este type VisibilityTypes = VISIBILITY.PUBLISH | VISBIBILITY.DRAFTme sale un error de espacio de nombres no encontrado, sin embargo, cuando los codifico parece funcionar?
— Max Carroll

Encontré un camino y agregué una nueva respuesta
— Max Carroll

10

Tal vez no sea exactamente lo que quería, pero Enumparece una solución perfecta para usted.

enum BraceStyle {Collapse, Expand, EndExpand, None}

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

Sin embargo, las enumeraciones están basadas en números. Significa que durante el tiempo de ejecución un valor real para, por ejemplo BraceStyle.Collapse, será 0 en este caso. Pero puede usarlos con otros scripts, incluso no mecanografiados, ya que se compilan en objetos. Así es como BraceStylese verá después de compilar y ejecutar:

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

Si desea cadenas en su lugar, puede usar una clase con miembros estáticos, como se describe aquí


enums pueden tener valores de cadena (ahora al menos, no estoy seguro si podrían hacerlo en 2014). enum BraceStyle { Collapse = "Collapse", Expand = "Expand" }.
— ZachB

Si pudieran en 2014, mencionaría eso en mi respuesta.
— Kuba Jagoda

8

TS ofrece una tipificación de valores de cadena específicos, que se denominan tipos literales de cadena .

Aquí hay un ejemplo de cómo usarlos:

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

En TypeScript 2.4 en adelante puede usar String Enums

Estoy a favor de este enfoque porque evita la necesidad de tener la misma cadena codificada en más de un lugar.

Es posible hacer una enumeración donde los valores son cadenas

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

Esta enumeración se puede usar como un tipo en una interfaz o clase

export interface UserOptions  {
  visibility:  VISIBILITY 
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.