我正在为第三方js库创建一个TypeScript定义文件。其中一个方法允许使用options对象,而options对象的一个属性接受列表中的字符串:"collapse"、"expand"、"end-expand"和"none"。

我有一个接口的选项对象:

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

接口是否可以强制执行这一点,因此如果您包含带有brace_style属性的IOptions对象,它将只允许可接受列表中的字符串?


当前回答

您很可能需要枚举选项。但如果你不这样做,并且你真的需要你的const存在,这里的一些回答帖子的keyOf是有效的,只是稍微修改了一下:

export const BRACE_STYLES = {
  collapse: 'collapse',
  'end-expand': 'end-expand',
  expand: 'expand',
  none: 'none'
}

export type BraceStyle = keyof typeof BRACE_STYLES

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

这实际上会让你得到你想要的"collapse" | "expand" | "end-expand" | "none"效果,仍然允许const存在,而不需要对类型进行硬编码。

其他回答

也许不是你想要的,但enum似乎是一个完美的解决方案。

enum BraceStyle {Collapse, Expand, EndExpand, None}

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

然而,枚举是基于数字的。这意味着在运行时一个实值,例如BraceStyle。这里崩溃值为0。但是您可以将它们用于其他脚本,甚至是非typescript脚本,因为它们被编译为对象。这是BraceStyle在compile&run之后的样子:

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

如果需要字符串,可以使用带有静态成员的类,如下所述

您可以创建由其他人指定的自定义类型。 我想补充一点,你也可以从对象const推断创建的类型:

export const braceStyles = {
  collapse: "collapse",
  expand: "expand",
  end-expand: "end-expand",
  none: "none"
}

export type braceStyle = typeof braceStyles[keyof typeof braceStyles]

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

这样你就不必使用enum,你也可以在任何需要它们的地方使用对象属性,在那里它们的类型将是string,而不是enum.member

对象与枚举

在TypeScript 2.4以后,你可以使用字符串枚举

我喜欢这种方法,因为它避免了在多个地方使用相同的硬编码字符串的需要。

可以创建一个枚举,其中值为字符串

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

这个枚举可以用作接口或类上的类型

export interface UserOptions  {
  visibility:  VISIBILITY 
}
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

您很可能需要枚举选项。但如果你不这样做,并且你真的需要你的const存在,这里的一些回答帖子的keyOf是有效的,只是稍微修改了一下:

export const BRACE_STYLES = {
  collapse: 'collapse',
  'end-expand': 'end-expand',
  expand: 'expand',
  none: 'none'
}

export type BraceStyle = keyof typeof BRACE_STYLES

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

这实际上会让你得到你想要的"collapse" | "expand" | "end-expand" | "none"效果,仍然允许const存在,而不需要对类型进行硬编码。