#
Advanced Types | webally.co.za
#
Type Alias
type User = {
readonly id: number,
name: string,
retire: (date: Date) => void
}
Now there is a new type called User
that I can use for all User
types
let user: User = {
id: 1
name: 'Shaun',
retire: (date: Date) => {
console.log(date)
}
}
#
Union Types
// I declare a function that can take either a number or a sting for the weight argument,
// We call this union types
function kgToPounds(weight: number | string):number {
// The code completion will only give suggestions of methods that is common to string and numbers, but byh using narrowing, you can get the fill code completion for either a number or a sting
if (typeof weight === 'number') {
return weight * 2.2;
} else {
return parseInt(weight) * 2.2;
}
}
#
Intersection Type
Instead of using the pipe |
between the various types, use the &
character to define a an intersection type. Here is an example of an intersection type
type Draggable = {
drag: {} => void
};
type Resizeable = {
resize: {} => void
};
// UIWidget is Draggable and Resizeable at the same time, making it an intersection type
type UIWidget = Draggable & Resizeable;
Now create an Element that implements UIWidget, it needs to implement both the methods, the drag()
method and the resize()
method
let textBox: UIWidget = {
drag() => {},
resize() => {}
}
#
Literal Type
// The variable below can either have a value if 10 or 20
let qty: 10 | 20 = 20;
Or we can create a new Type that does the same
// Creating a new type
type Qty = 10 | 20;
// Using the new literal type
let qty: Qry = 10;
#
Nullable Types
function greet(name: string) {
console.log(name.toUpperCase());
}
// This will give an error because in the function it is going to try and do a `toUpperCase()` on the `null`. So the compiler will moan about this, and won't allow this to happen.
greet(null);
There is a TypeScript
setting that you can set to false
to, so that it won't give and error
"strictNullChecks": false
- But it is not a good idea to ever turn off that check.
- The best thing to do here is to make use of a union type again...
function greet(name: string | null) {
console.log(name.toUpperCase());
}
greet(null);
- And if you want to be able to pass
undefined
as well...
function greet(name: string | null | undefined) {
console.log(name.toUpperCase());
}
greet(undefined);
#
Optional Chaining
It will happen that you will often do null checks
function getCustomer(id: number): Customer | nul | undefined {
return id === 0 ? null : { birthday: new Date()};
}
let customer = getCustomer(0);
// Then I must perform all the checks below, before I can check for the birthday, otherwise it might happen that I try to get the birthday of `null` or `undefined`
if (customer !== null && customer !== undefined) {
console.log(customer.birthday);
}
#
Optional Property Access Operator
There is an easier way to do all of those checks by using the optional property access operator
// the question mark `?` before the `.birthday` is called the `optional property access operator`, the the code below will only be executed of customer is not null or undefined
console.log(customer?.birthday);
Now lets get the year of the Birthday
console.log(customer?.birthday?.getFullYear());
#
Optional Element Access Operator
// So to make sure the customer is not null or undefined, you need to do the following checks
if (customers !== null && customers !== undefined) {
customers[0];
}
- Or you can do the same checks by using the
Optional Element Access Operator
customers?.[0];
Above the ?.
is the Optional Element Access Operator
#
Optional call Operator
let log: any = {message: string} => console.log(message);
// Or it could be declared like
let log: any = null;
// So if I would not try and do the following
log('a');
// it will crash because log is null
So to get past this you can use the Optional call Operator
log?.('a')l
The ?.
is the Optional call Operator
. And the log function will only be called if it is an actual function