如何在 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(";")
我有这个类型声明:
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(";")