Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending a string in TypeScript

When using generics in TypeScript, you sometimes see a type Parameter such as:

T extends string

Isn’t this the same as using string directly? Can you subclass string? What would this be good for?

like image 344
Golo Roden Avatar asked Aug 03 '19 20:08

Golo Roden


People also ask

Can you extend types in TypeScript?

Extending types in TypeScript can be done by using the & operator. This is called intersection types that can be used for combining two or more different types together. The Tomato type will now contain both fields from the other two types. You can combine as many types together this way as needed.

What is ?: In TypeScript?

What does ?: mean in TypeScript? Using a question mark followed by a colon ( ?: ) means a property is optional. That said, a property can either have a value based on the type defined or its value can be undefined .

What is type guard in TypeScript?

A type guard is a TypeScript technique used to get information about the type of a variable, usually within a conditional block. Type guards are regular functions that return a boolean, taking a type and telling TypeScript if it can be narrowed down to something more specific.


2 Answers

type narrowedString =  "foo" | "bar"

// type ExtendsString = true
type ExtendsString = "foo" extends string ? true : false 

"foo" and "bar" extend both the string type. For example that is useful, when you want to define enum like data structures (without the built in TypeScript enum type) or constants.

When a function offers a generic type parameter which extends string like T extends string, you can use that to enforce strong typing for your enums/constants.

function doSomething<T extends string>(t: T): {a: T} {
...
}

// invoke it
doSomething("foo" as const) // return {a: "foo"}

Don't make the mistake to lump extends in TypeScript's typesystem together with extends from ES classes - they are two complete distinct operators.

class extends corresponds to instanceof and exists in the runtime as a construct, whereas in the type system extends e.g. occurs with Conditional types,can be translated with "is assignable to" and is only for compile time.

Update:

You can find out more about String Literal Types in the TypeScript docs.

like image 143
bela53 Avatar answered Sep 18 '22 22:09

bela53


Here is a simple example of how you might extend a string and how hard coding the type would break it.

type Foo = string & Partial<{ meta: string }>

const foo: Foo = 'foo';
foo.meta = 'this string is important';

function hardCoded(x: string): string {
  return x;
}

hardCoded(foo).meta;  // this is an error

function generic<X extends string>(x: X): X {
  return x;
}
generic(foo).meta;  // but this works
like image 34
cyberixae Avatar answered Sep 20 '22 22:09

cyberixae