如何在 TypeScript 中使用预定义的可接受值正确声明自定义类型?

How to declare custom type correctly with predefined acceptable values in TypeScript?

我有这个类型声明:

declare const csvSeparator: unique symbol;
export declare type CSVSeparator = ';' | ',' | ' ' | '|' | '.' | '\t'
  & { readonly [csvSeparator]: 'CSVSeparator' };

然后我尝试定义这个结构:

const predefinedColumnSeparators: ColumnSeparatorInterface[] = [
  {name: 'Semicolon', character: ';'},
  {name: 'Comma', character: ','},
  {name: 'Space', character: ' '},
  {name: 'Pipe', character: '|'},
  {name: 'Colon', character: '.'},
  {name: 'Tabulator', character: '\t'},
];

但是在这里我得到一个错误 Type '"\t"' is not assignable to type 'CSVSeparator'

如何正确声明我的自定义类型?或者有没有更好的方法来定义可接受的值?

我不确定你想如何使用 CSVSeparator,但你可以改用 enum

enum CSVSeparator {
  Semicolon = ";",
  Comma = ",",
  Space = " ",
  Pipe = "|",
  Colon = ".",
  Tabulator = "\t"
}

您已将 CSVSeparator 中的 '\t' 设为 nominal string type(也称为品牌原语)。分配错误发生,因为无法再将常规 '\t' 字符串分配给此标称 '\t'。此外,标称类型(交集部分)仅适用于 '\t':

type CSVSeparator = ... | ... | ('\t'  & { readonly [csvSeparator]: 'CSVSeparator' })`
// read like this:              ^                                                   ^

我认为,您在这里有两个选择:1. 使用常规字符串(简单的字符串)或 2. 品牌字符串(更强的类型)。

1.简单字符串 (Code)

export type CSVSeparator = ';' | ',' | ' ' | '|' | '.' | '\t'

const predefinedColumnSeparators: { name: string; character: CSVSeparator }[]  = [
  {name: 'Semicolon', character: ';'},
  ...
  {name: 'Tabulator', character: '\t'},
];

2。品牌字符串 (Code)

declare const csvSeparator: unique symbol;

// nominal string type
type Branded<T extends string> = T & { readonly [csvSeparator]: 'CSVSeparator' }

// helper function: create branded string by applying a type assertion to it
function brand<T extends string>(s: T) {
    return s as Branded<T>
}

export type CSVSeparator = Branded<';'> | Branded<','> | Branded<' '> | Branded<'|'>
    | Branded<'.'> | Branded<'\t'>

const predefinedColumnSeparators: { name: string; character: CSVSeparator }[] = [
    { name: 'Semicolon', character: brand(';') },
    { name: 'Semicolon', character: ';' }, // error, no regular string assignable 
    ...
    { name: 'Tabulator', character: brand('\t') }
];

branding 只是编译时的类型声明,你可以正常使用它 string:

const regularString: string = brand(";")