如何在 TypeScript 界面中要求特定的字符串

Posted

技术标签:

【中文标题】如何在 TypeScript 界面中要求特定的字符串【英文标题】:How to require a specific string in TypeScript interface 【发布时间】:2015-01-07 10:37:45 【问题描述】:

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

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

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

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

【问题讨论】:

请重温这个问题的答案 有点像@Andreas 的评论,为什么你更喜欢RyanQ 的回答而不是Denis Khay's? Denis' 似乎更广泛地适用于 imo。 【参考方案1】:

也许不是您想要的,但Enums 似乎是您的完美解决方案。

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

如果您想要字符串,则可以使用具有静态成员的类,如 here 所述

【讨论】:

enums 可以有字符串值(现在至少,不确定 2014 年是否可以)。 enum BraceStyle Collapse = "Collapse", Expand = "Expand" . 如果他们可以在 2014 年,我会在我的回答中提到这一点。【参考方案2】:

这是在 1.8 版中作为“字符串文字类型”发布的

What's New in Typescript - String Literal Types

页面示例:

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

【讨论】:

它需要在应用程序中的任何地方复制和粘贴带有字符串的行,您需要将这种类型的字符串作为参数传递。如果您总是使用整个 AnimationOptions,那么该解决方案似乎没问题,但对于您可能只传递“缓动”类型的用例,这是错误的。请参阅 Denis Khay 的回答,这要好得多。【参考方案3】:

试试这个

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

export interface IReadings 
   param:ReadingTypes

编辑:非常感谢您的支持,但是,随着时间的推移,我逐渐成长为一名开发人员 :),现在在大多数情况下,我不再推荐这种方法了。是的,它仍然有效,但关键是上面的结构与枚举结构非常相似,所以为什么不使用枚举来代替(优点如下):

export enum ReadingTypes 
    Some = 'some',
    Variants = 'variants',
    Of = 'of',
    Strings = 'strings',

export interface IReadings 
   param: ReadingTypes

优点:(是的,可能更像是恕我直言,我理解,但是,尽管如此)

    例如在代码中看到它更具可读性
if(item.reading === 'some') 
...

// vs 
if(item.reading === ReadingTypes.Some) 
...

在第一种情况下,当您阅读无法捕捉到的代码时,乍一看,.reading 字段只能包含几个特定的​​参数,而不是任何字符串值。

    当您编写代码时,如果您使用枚举,您的编辑器将获得更好的帮助 - 记住枚举的名称并编写它就足够了,它会显示枚举的所有变体。是的,对于第一种类型('some' | 'variants' ... )它也可以这样做,但它做得更少.. um.. 热切

【讨论】:

这应该被标记为正确,因为它允许在应用程序的任何地方重用创建的类型。 这正是我一直在寻找的一种将字符串数组作为值传递给枚举类型的方法。通过完全跳过枚举并使用type,我能够通过以下示例:const myVar: ReadingTypes = ["some"|"variants"];,同时仍保持动态枚举类型语法。完全同意这应该是标记为正确的答案。 有没有办法使用它,但像这样轻柔地输入type VisibilityTypes = VISIBILITY.PUBLISH | VISBIBILITY.DRAFT 我得到一个命名空间未找到错误,但是当我对它们进行硬编码时,它似乎可以工作 我找到了一个方法,并添加了一个新的答案 我首先尝试将类型设为 'json' | 'text' 它没有用,但是当我将它设置为 ResponseType 然后输入 ResponseType = 'json' | 'text' 确实有效,谢谢!【参考方案4】:
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

【讨论】:

【参考方案5】:

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';

【讨论】:

【参考方案6】:

在 TypeScript 2.4 以后,您可以使用 String Enums

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

可以创建一个值是字符串的枚举

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

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

export interface UserOptions  
  visibility:  VISIBILITY 

【讨论】:

【参考方案7】:

enum 可能是最好的解决方案,但是如果您将值作为 const 对象的键并且您无法更改它,则语法将是

brace_style?: typeof BRACE_STYLES[keyof typeof BRACE_STYLES];

BRACE_STYLES 是 const 对象的名称

【讨论】:

以上是关于如何在 TypeScript 界面中要求特定的字符串的主要内容,如果未能解决你的问题,请参考以下文章

Typescript 对象:如何将键限制为特定字符串?

如何键入 Typescript 数组以仅接受一组特定的值?

TypeScript - 特定的字符串类型

如何在对象数组中显示特定对象(Angular 5,TypeScript)

如何将字符串类型转换为 Typescript 中的一种对象类型?

如何在 TypeScript 中正确要求和声明节点库类型?