The Basics Flashcards
What are conditional types ?
Conditional types are useful for removing type within a type.
Types that we create can have conditional logic, just like regular JavaScript code.T1 extends T2 ? A : B
The extends keyword is used to define the condition. If T2 is within T1 then type A is used; otherwise, type B is used.
What is NonNullable ?
It’s a standard utility type in TypeScript that is implemented using a conditional type to remove null and undefined from the type passed into it.
What will Example1 resolve to:
~~~
type Person = {
name: string;
age: number;
};
type Example1 = Person extends {} ? string : number;
~~~
string
Note: this is an example of a conditional type.
Create a utility type that remove null using conditional type. Name your type RemoveNull
type RemoveNull<T> = T extends null ? never : T;</T>
What is the use of the infer keyword?
There is an infer keyword that can be used within a condition in a conditional type to put the inferred type into a variable. That inferred variable can then be used within the conditional branches.
What will be the type of item1 and item2 here:
~~~
type ArrayElementType<T> = T extends (infer E)[] ? E : T;</T>
type item1 = ArrayElementType<number[]>;
type item2 = ArrayElementType<{ name: string }>;
~~~
item1 is number
item2 is {name: string}
Review this conditional type…
~~~
function addPerson(personName: string) {
return {
type: “AddPerson”,
payload: personName
};
}
function removePerson(id: number) {
return {
type: “RemovePerson”,
payload: id
};
}
type AddPersonType = typeof addPerson;
type RemovePersonType = typeof removePerson;
type FunctionReturnType<T> = T extends (...args: any) => infer R ? R : T;</T>
type Actions =
| FunctionReturnType<AddPersonType>
| FunctionReturnType<RemovePersonType>;</RemovePersonType></AddPersonType>
type Actions =
| FunctionReturnType<AddPersonType>
| FunctionReturnType<RemovePersonType>;</RemovePersonType></AddPersonType>
~~~
What is the type Actions equivalent to?
Actions is equivalent to the type below:
{ type: string; payload: string; } | { type: string; payload: number; }
Note: this will work even if you are using an object instead of a function.
Here is a version that works only on functions:
function addPerson(personName: string) { return { type: "AddPerson", payload: personName }; } function removePerson(id: number) { return { type: "RemovePerson", payload: id }; } type AddPersonType = typeof addPerson; type RemovePersonType = typeof removePerson; type FunctionReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : T; type Actions = | FunctionReturnType<AddPersonType> | FunctionReturnType<RemovePersonType>;
What is this doing?~~~type ReturnType<T extends (…args: any) => any> = T extends ( …args: any) => infer R ? R
: any;
~~~
Gives the return type of the function.
What is ReturnType
It is a standard TypeScript utility type. It return the return type of a function.
What will be the type of ContactKeys in:
~~~
const person = {
name: “Fred”,
age: 30,
email: “fred@somewhere.com”
};
console.log(person);
type RemoveFromUnion<T, K> = T extends K ? never :T;
type ContactKeys = RemoveFromUnion<keyof typeof person, “age”>;
~~~
‘name’ | ‘email’
Note our RemoveFromUnion is the same as the standard utility type called Exclude.
What will be the type of Contact here:
~~~
const person = {
name: “Fred”,
age: 30,
email: “fred@somewhere.com”
};
type ObjectWithKeys<T, K extends keyof T> = {
[P in K]: T[P];
};
type Contact = ObjectWithKeys<typeof person, “name” | “email”>;
~~~
{ name: string; email: string; }
Note: This is the same type as a standard utility type called Pick.
What will be the type of Profile here:
~~~
const person = {
name: “Fred”,
age: 30,
email: “fred@somewhere.com”
};
type ObjectWithKeys<T, K extends keyof T> = {
[P in K]: T[P];
};
type Contact = ObjectWithKeys<typeof person, “name” | “email”>;
type RemoveFromUnion<T, K> = T extends K ? never : T;
type ObjectWithoutKeys<T, K extends keyof T> = ObjectWithKeys<
T,
RemoveFromUnion<keyof T, K>
>;
type Profile = ObjectWithoutKeys<typeof person, “name” | “email”>;
~~~
{ age: number; }
This is the same type as a standard utility type called Omit.
What is the readonly modifier and what is its syntax?
The readonly modifier allows immutable primitive properties to be created. However, this is only compile-time immutability and not runtime immutability.
In the next lesson, we will learn how to create immutable objects and array properties.
type TypeName = { readonly propertyName: PropertyType; }; interface InterfaceName { readonly propertyName: PropertyType; } class ClassName { constructor(public readonly propertyName: PropertyType) {} }
Will Typescript prevent readonly properties to be changed at runtime?
No. TypeScript will only raise a type error. It won’t stop readonly properties from actually being updated at runtime. TypeScript doesn’t exist at runtime to prevent such updates.
Create a class called Vehicule with 2 properties. name (string) and topspeed a readonly number.
class vehicule { constructor(name:string, readonly topSpeed:number){} }
Is it possible to stop the reference from changing? For example on a property that is a referenced type?
Yes. The readonly modifier can be placed before a property that is a reference type (i.e. an object or an array) as follows:
~~~
type TypeName = {
readonly propertyName1: ObjectType;
readonly propertyName2: ArrayType;
};
~~~
This can also be used in interfaces and classes:
~~~
interface InterfaceName {
readonly propertyName1: ObjectType;
readonly propertyName2: ArrayType;
}
class ClassName {
constructor(
public readonly propertyName1: ObjectType,
public readonly propertyName2: ArrayType
) {}
}
~~~
This will stop the property’s reference from changing so that it can’t be changed to another object or array. It, however, doesn’t stop values within the property from changing.
Will this prevent the array content from changing ?
readonly propertyName: ArrayType;
No. This will stop the property’s reference from changing so that it can’t be changed to another object or array. It, however, doesn’t stop values within the property from changing.
The readonly modifier can be placed before a property that is a reference type (i.e. an object or an array) as follows:
type TypeName = { readonly propertyName1: ObjectType; readonly propertyName2: ArrayType; }; This can also be used in interfaces and classes: interface InterfaceName { readonly propertyName1: ObjectType; readonly propertyName2: ArrayType; } class ClassName { constructor( public readonly propertyName1: ObjectType, public readonly propertyName2: ArrayType ) {} }