Is there a way in Typescript to define a type that is only a string literal, excluding string
itself?
Note that I am not talking about a certain list of string literal; for which, a simple union of "Value1" | "Value2"
, or an enum
type would work. I am talking about any string literal, but not string
itself.
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
I am doing Branding on the types in my code, and I am passing a brand name, as a template, to my parent class. See the code below:
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
Playground Link
I want to make sure every subclass is passing exactly a string literal, and not just string
to the parent class.
Use the Record utility type to enforce the type of an object's values in TypeScript, e.g. type Animal = Record<string, string> . The Record utility type constructs an object type, whose keys and values are of specific type. Copied!
The string literal type allows you to specify a set of possible string values for a variable, only those string values can be assigned to a variable. TypeScript throws a compile-time error if one tries to assign a value to the variable that isn't defined by the string literal type.
Hence, you can treat a variable that has a string literal type like a variable of type string . You can access properties, call methods, and use operators, just as you would with regular strings: const eventName: "click" | "mouseover" = "click"; eventName. length; // 5 eventName.
A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string.
I found an answer that works for my use case, but is not the most reusable one. Just sharing it anyway.
I believe it's not possible to have one solid type to represent what I wanted, because I cannot even think what will show up in VS Code if I hover over it!
However, to my knowledge, there is a function-style checking in Typescript for types that you can pass a type in and expect a type back, and finally assign a value to it to see if it goes through.
Using this technique I am thinking about the following template type:
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!
Playground Link
Also, in my use case, I am doing:
abstract class MyAbstractClass<
BRAND_T extends (string extends BRAND_T ? never : string),
VALUE_T = string
> {
...
Playground Link
... which works like a charm!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With