string
Types text primitives — the lowercase form, not the String wrapper object.
let myName: string = "Alice";- Added in TypeScript 1.0
Errors
Assigning a String wrapper object to a string is a compile error: "Type 'String' is not assignable to type 'string'."
Changelog
- PHP 4.1Template literal types added: `Hello, ${string}` is a type, and string manipulation types Uppercase, Lowercase, Capitalize and Uncapitalize were introduced.
- PHP 4.3Template literal type inference improved for pattern matching on string literal types.
string is the type of JavaScript text values, written with single quotes, double quotes or backticks. There is no separate character type — a single character is a string of length one.
Why lowercase
The capitalised String is legal but refers to the boxed wrapper interface, the object you get from new String("x"). Its typeof is "object", it is never equal to a primitive under ===, and it is not assignable to string. The handbook's guidance is unambiguous: always use string, and the same applies to number, boolean and symbol. Only reach for String when you are describing the global constructor itself.
Narrower than string
Often string is too wide. A string literal type ("draft" | "live") restricts the value to a known set, and a template literal type (TypeScript 4.1) describes a shape: `/api/${string}`, `${number}px`. Combined with Uppercase, Capitalize and friends, these turn string-keyed conventions into things the compiler can check.
Remember that .length counts UTF-16 code units, not characters — an emoji outside the BMP counts as two.
Example
When to use it
- Restricting an option to known values with a string literal union instead of plain string
- Enforcing a route or CSS-unit shape with a template literal type
- Explaining why a legacy `String` annotation in a .d.ts must be replaced with `string`
Frequently asked questions
What is the difference between string and String in TypeScript?
`string` is the primitive type; `String` is the boxed wrapper object interface. A `String` instance has `typeof "object"`, is never `===` a primitive, and is not assignable to `string`. The handbook says always use lowercase `string`, and the same applies to `number`, `boolean` and `symbol` — the capitalised forms are only for describing the global constructors.
Is there a char type in TypeScript?
No — a single character is just a `string` of length one. If you need to constrain the value, use a string literal union such as `"a" | "b" | "c"`, or a template literal type for a shape. Note that `.length` counts UTF-16 code units, so astral characters like most emoji count as two.
How do I restrict a string to specific values?
Use a string literal union: `type Status = "draft" | "live"`. Assigning any other string is then a compile error. To derive the union from an existing array, declare it `as const` and use `typeof arr[number]`; to constrain a shape rather than a set, use a template literal type such as `` `/api/${string}` ``.
More examples
Narrowing string to a literal union
Prints `Visible to everyone`, `[ 'archived', 'draft', 'live' ]`, and `[ 'Not published', 'Hidden' ]`. The `Record<Status, string>` forces every member to have a label — remove one and tsc reports the missing key. A `const` initialised with a string literal keeps the literal type, which is why `fromConfig` is accepted where `Status` is required.
type Status = "draft" | "live" | "archived";
const labels: Record<Status, string> = {
draft: "Not published",
live: "Visible to everyone",
archived: "Hidden",
};
function label(s: Status): string {
return labels[s];
}
const fromConfig = "live"; // inferred as string in a let, literal in a const
console.log(label(fromConfig));
console.log(Object.keys(labels).sort());
// label("published") // Error: Argument of type '"published"' is not assignable
// // to parameter of type 'Status'.
console.log((["draft", "archived"] as Status[]).map(label));Template literal types for route shapes
Prints `/api/users/1 320px onClick`, `640`, `48`. Template literal types check the shape of a string at compile time, so a route missing its `/api` prefix or a length missing its unit is rejected before it reaches `parsePixels`. `Capitalize<T>` is one of the four intrinsic string manipulation types added alongside them in 4.1.
type ApiRoute = `/api/${string}`;
type Pixels = `${number}px`;
type EventName<T extends string> = `on${Capitalize<T>}`;
const route: ApiRoute = "/api/users/1";
const width: Pixels = "320px";
const handler: EventName<"click"> = "onClick";
function parsePixels(v: Pixels): number {
return Number(v.slice(0, -2));
}
console.log(route, width, handler);
console.log(parsePixels(width) * 2);
console.log(parsePixels("48px"));
// const bad: ApiRoute = "/users/1"; // Error: not assignable to '`/api/${string}`'.
// const bad2: Pixels = "320"; // Error: not assignable to '`${number}px`'.
Discussion