Typescript中是否有一种方法可以定义仅string literal的类型,而排除string
本身呢?
请注意,我并不是在谈论某些字符串文字。为此,可以使用"Value1" | "Value2"
或enum
类型的简单联合。我说的是任何字符串文字,而不是string
本身。
type OnlyStringLiterals = ...; // <--- what should we put here?
const v1: OnlyStringLiterals = "hi"; // should work
const v2: OnlyStringLiterals = "bye"; // should work
// and so should be for any single string value assigned
// But:
const v3: OnlyStringLiterals = ("red" as string); // should NOT work -- it's string
我正在对代码中的类型进行Branding,并且正在将品牌名称作为模板传递给父类。请参见下面的代码:
abstract class MyAbstractClass<
BRAND_T extends string,
VALUE_T = string
> {
constructor(private readonly _value: VALUE_T) { }
getValue(): VALUE_T { return this._value; }
private _Brand?: BRAND_T; // required to error on the last line, as intended!
}
class FirstName extends MyAbstractClass<"FirstName"> {
}
class AdminRole extends MyAbstractClass<"AdminRole"> {
}
class SubClassWithMissedName extends MyAbstractClass<string> {
// I want this to error! ........................ ^^^^^^
}
function printName(name: FirstName) {
console.log(name.getValue());
}
const userFirstName = new FirstName("Alex");
const userRole = new AdminRole("Moderator");
printName(userRole); // Already errors, as expected
我想确保每个子类都传递一个字符串文字,而不仅仅是string
传递给父类。
答案 0 :(得分:3)
我找到了一个适用于我的用例的答案,但不是最可重用的答案。还是分享吧。
我相信不可能有一个实体类型来表示我想要的内容,因为我什至无法想到如果将鼠标悬停在VS Code上会显示什么内容!
但是,据我所知,Typescript中有一个函数样式检查,您可以传递一个类型并期望返回一个类型,并最终为其赋值以查看其是否通过。
使用这种技术,我正在考虑以下模板类型:
type TrueStringLiterals<T extends string> = string extends T ? never : true;
const v1 = "hi";
const check1: TrueStringLiterals<typeof v1> = true; // No error :-)
const v2 = "bye";
const check2: TrueStringLiterals<typeof v2> = true; // No error :-)
const v3 = ("red" as string);
const check3: TrueStringLiterals<typeof v3> = true; // Errors, as expected!
此外,在我的用例中,我正在做:
abstract class MyAbstractClass<
BRAND_T extends (string extends BRAND_T ? never : string),
VALUE_T = string
> {
...
...就像魅力一样!
答案 1 :(得分:1)
您可以创建仅允许在字符串子集上使用的实用程序类型:
type SubString<T> = T extends string ?
string extends T ? never
: T
: never
const makeSubStr = <T extends string>(a: SubString<T>) => a
const a = makeSubStr('strLiteral')
const b = makeSubStr('strLiteral' as string) // error
const c: string = 'elo I am string'
const d = makeSubStr(c) // error
const e: SubString<"red"> = ("red" as string); // error
如果某些内容不是字符串,则此类型也将返回never
,在您的回答TrueStringLiterals
中将不考虑这种情况并将其传递。