TypeScript
TypeScript Language Basics
Primitive Types (Boolean, Number, String)
Boolean
let isDone: boolean = false;
Number
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;
String
let color: string = "blue";
let fullName: string = 'Bob Bobbington';
let age: number = 37;
let sentence: string = `Hello, my name is ${fullName}.
I'll be ${age + 1} years old next month.`;
Arrays
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];
Continue reading TypeScript Creating Object Field Names as Union Type if Field Type is Function
When you remove [keyof T]
section in line 169, you will see a big difference.
As you see in the following screenshot, it created an Union Object Type, but most of the field types are never
. That's why, in order to list values of type, we need to have that deleted section.
TypeScript Creating Object Field Names as Union Type Usages
In order to support Union Type, I used Conditional Type.
type ObjectFieldNames<T> = T extends any ? keyof T : never;
type ObjectFieldNames<T> = T extends { [P in infer A]: any } ? A : never;
type ObjectFieldNames<T> = T extends Record<infer K, any> ? K : never;
TypeScript Union Type and Distributive Conditional Types
When conditional types act on a generic type, they become distributive when given a union type.
So, in order to support Union Type, use Conditional Type because it works as loop.
Generic Type with Single Type without Distributive Conditional Type
Generic Type with Union Type without Distributive Conditional Type (This doesn't work)
Notice that conditional type is not use in line 96 so ObjectFieldNames
function couldn't retrieve field names in line 102.
Generic Type with Union Type and Distributive Conditional Type
You can think Union type as array, so conditional type will iterate for each type in Union.
For example, notice that PersonType | UserType
is used as Union Type in line 113, and field names of both types are listed in Popup window as shown in below screenshot.
PersonType | UserType | EventType
is used as Union Type in line 115, so Popup window showed more fields in the following screenshot.
for example PersonType | UserType | EventType
, then ObjectFieldNames<T>
is keyof PersonType | keyof UserType | keyof EventType
TypeScript Covariance and Contravariance
I want to share a small part of wikipedia description firstly then will continue with example codes.
Assume that we work with below types.
Animal is Supertype.
Dog and Cat are Subtype.
Covariance
Covariance means that Subtypes can be assigned to Supertypes. This is also known as Polymorphism or Subtyping. So Covariance = Polymorphism = Subtyping
In other words, Dog(Subtype) can be assigned to Animal(Subtype) or Dog(Subtype)
Generic types are also covariant.
Continue readingTypeScript Narrowing Function Return Type Part 2
TypeScript Narrowing Function Return Type Part 1
Narrowing return type of function is a little bit strange in TypeScript. So I share use cases below from bad to good 🙂
Use Cases
Usage 1 – Bad usage
Notice that even I call foo(0)
in line 8, when I hover mouse on foo
in line 8, popup shows val parameter type as string | number
union type. But it should show as number. So it is not narrowing parameter and return type of function.
Usage 2 – Bad usage
This usage narrows parameter and return type of function as literal type. But we need to narrow to type of parameter not value of parameter as literal type. Popup shows generic parameter type as 0
, that's why, parameter and return type becomes 0
.
Usage 3 – Good usage (function overloads)
Continue readingTypeScript Function Parameter Inference
TypeScript Conditional Types Good Usage Part 2
The aim of this code is simply to show related fields in data
field dependent on eventType
.
When ChangePassword
is selected in eventType
filed, then userName
, oldPassword
and newPassword
are becoming as required fields.
When ForgotPassword
is selected in eventType
field, then userName
is just becoming required.
const msg1 = publishMessage?.({
eventType: 'ChangePassword',
data: {
userName: '',
oldPassword: '',
newPassword: '',
},
subject: '',
topic: '',
});
const msg2 = publishMessage?.({
eventType: 'ChangePassword_Success',
data: {
emailSubject: 'Password Verification code is ######',
emailMessage: '',
},
subject: '',
topic: '',
});
const msg3 = publishMessage?.({
eventType: 'ForgotPassword',
data: {
userName: ''
},
subject: '',
topic: '',
});
const msg4 = publishMessage?.({
eventType: 'ForgotPassword_Success',
data: {
resetPasswordVerificationCode: '',
emailSubject: '',
emailMessage: ''
},
subject: '',
topic: '',
});
Continue reading