As TypeScript applications get more complex so do the types required to describe it. There are a number of built-in types that can be used for this purpose or combined to create more specialised types.

What I term modifying types such as Partial and Required are included in the language and I will quickly cover these first to warm up for the deeper types we’ll address later.

This article will quickly move on to focus on the slightly more advanced types beginning with Extract. You can see the source of the various types by looking at the lib.es5.d.ts declaration file inside TypeScript.

Partial

This generic type takes a single argument, an object type, and returns a new type where all the properties are defined as optional.

With the application of the Partial type TypeScript will interpret User as the following type where all properties are now optional.

You can also get a little creative and keep some properties required when applying partial.

Whilst this works and the name property is now mandatory there are easier ways to do this that will become apparent further into this article.

Required

Much like partial this type takes a single argument of an object type and returns a new type where all the properties are required.

Creates a new type with the following form when interpreted by TypeScript.

Readonly

Pretty much what it says on the tin; this type marks all the properties of an object type as readonly.

Revealing a new TypeScript type that takes the following shape.

Record

This type is a little different to the three types that we’ve already reviewed so far; it takes two arguments. A union of keys and a type. With this information TypeScript will construct a new type that includes each of these keys set to the supplied type.

Which TypeScript will expand into the following type when it is interpreted.

Again, you can get a little creative with this type and do some things like this.

Will create a type when interpreted that looks a lot like what you might write as:

Another neat trick is to use Record to create types that include properties of multiple types.

That will create a type that will be interpreted into the following:

Extract (better known as intersection)

Set notation: A∩B

Extract venn diagram: includes a and b, but excludes x and z
Extract venn diagram: includes a and b, but excludes x and z

Items that exist in both the first and second arguments to the type are kept, but unique items from either side are dropped. This type essentially fills the role of an intersection between two types.

Describing the same operation in TypeScript code this type could be written using the in-built Array.prototype.filter() function.

If you have a two union types and you want to the find the intersection then Extract is very useful.

Exclude (better known as difference)

Set notation: A – B

Exclude venn diagram: includes x, but excludes a, b and z
Exclude venn diagram: includes x, but excludes a, b and z

Calculates the difference between two types (important to note that this is not the symmetrical difference). Everything that exists in the first argument excluding all items that appear in the second argument will be included in the resultant type.

This can also be described by the following TypeScript implementation code.

Exclude is used to narrow union types back down again. I am including the following code as a demonstration, but it is not production ready code and in some ways takes the form of pseudocode.

Pick

Set notation: A∩B

Pick venn diagram: includes a and b, but excludes x
Pick venn diagram: includes a and b, but excludes x

Similar to an intersection, but it is based on the keys defined in the first type argument. The second argument is a list of the keys to copy into the new type.

Here is a very contrived example of a possible use for Pick:

Omit

Set notation: A – B

Omit venn diagram: includes x, but excludes a and b
Omit venn diagram: includes x, but excludes a and b

Again, this type is similar to the Exclude type, but it takes an object type and a list of keys. The keys indicate which properties should be dropped from the new object type.

This has recently been added to the set of types that come with TypeScript by default in 3.5, but older code will need to implement this manually using code like the follow.

Notice how it builds upon two types that we’ve already looked at - Exclude and Pick.

Using the same example types as Pick we could have a function something like the following:

Difference (symmetrical)

Set notation: ’(A∩B) or (A∪B) - (A∩B)

Difference venn diagram: includes x and z, but excludes a and b
Difference venn diagram: includes x and z, but excludes a and b

Providing types for symmetrical difference is a little more difficult. This is where values that are unique from both the left and right should be included in the resultant type. Essentially this will lead to a final type that will be used in the following way.

As I mentioned this is a fair bit more difficult than it sounds and there are a number of steps required so hang in there.

To produce this we must first workout the difference between the keys in each of the input types. We’ll first write a key differencing type - AMinusB. This will take two object types and keep all the keys of A that do not exist in B.

The set notation for this is A - B (as you would expect) and that makes this type is very similar to one that we’ve just explored - Omit. AMinusB is a little different in that it can take any two objects and calculate the keys that exist in A, but not in B. Omit on the other hand dictates that the keys it is supplied are on the object it is given.

To get the symmetrical difference of the keys we can execute the AMinusB type twice and join them in a sum type.

Note that the key lists are flipped between the two calls to AMinusB so as to get key difference both ways - thus powering the “symmetrical” part of this difference type.

With these two key types we can now create the final differencing type that will take the keys and apply them to an object type. Given what we’ve already learned about the inbuilt types we know that Pick takes an object type and a list of keys and will return a new object type with just the specified properties/keys.

So, given SymmetricalKeyDiff and Pick we can create a symmetrical difference type. The input object for Pick is the union of A and B and the list of keys is the SymmetricalKeyDiff of A and B.

Putting this type into action looks something like this:

Intersection

Using the same basic underlying types it is also possible to get the intersection of two object types.

Put into practice this type can be used in the following way:

So, there you have it - some reasonably complicated types defined in TypeScript. Hopefully, you’ve been able to follow along until the end and you get some use out of what you’ve learnt here.