- This is the Typescript playground of useful examples which can save you a hell lot of time and help you mastering typescript with efficient implementation for type safety covering those cases which usually bother you when you encounter them.
- These cases can considerably improve your knowledge of Typescript and help you excel it.
- Many of these cases are usually asked in the interview
1. Lets discuss a case where you have variable which accepts an array and this array will always have first element as a string and the rest of the elements will be an object containing id and name.
Lets understand it with example
IData interface can be used to define the dataArray whose first element will always be string and all other elements from index 1 and so on will be an object will id and name as keys.
1 2 3 |
interface IData = [string, ...{id:number,name:string}[]] let dataArray:IData = [‘hello string’,{id:1,name:’david’},{id:2,name:’sevin’},{id:3,name:’viton’}] |
2. Suppose we have a function which accepts a parameter which can have objects with different keys so we can write a generic definition for the function
We are creating a function for validating if the object has any null values or not. There are two objects with their types defined below.
Both the objects have different keys but they are using a single generic function to validate if any key of the object has null value.
obj1 has a null value for company so the isvalid() function will return false and obj2 has no null value hence the function will return true.
As you can see, isvalid function parameter arg has a generic type as objType which can accept any object with any keys.
Check the example below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
type objtype1={ company:string | null; pincode:number; } type objtype2 ={ employeeCount:number; isHiring :boolean; department:null | string; } const obj1:objtype1 ={ company:null, pincode:23 } const obj2:objtype2={ employeeCount:1000, isHiring:false, department:'IT' } function isvalid<Type>(arg:Type):boolean{ for(const key in arg){ if(arg[key]===null){ return false; } } return true; } console.log(isvalid<objtype1>(obj1)); console.log(isvalid<objtype2>(obj2)); |
3. If you want to make a new type by extracting the keys of another interface but you don’t need to extract all the keys then we can make use of Exclude utility type to remove unwanted keys as shown below.
We need to make a new type which has only ‘id’ ,’name’,’canWork’ as accepted string values and excludes ‘comment’.
So using keyof we have extracted the keys of data object and then using Exclude we have excluded the key comment and created a new type called newData which will have the following structure
type newData = { ‘id’,”name”,”canWork” }
1 2 3 |
type data = { id:number; name:string; canWork:boolean; comment :string; } type newData = Exclude<keyof data,’comment’> |
Javascript object keys are always coerced to a string, so object[0] is always same as object[“0”].
4. What is the difference between Exclude and Omit Utility types.
In above example of 3rd point , we have seen that Exclude requires two parameters. 1st parameter accepts the union of strings and the second parameter includes the union of strings which needs to be removed from the first parameter to create a new type.
Omit does the same thing but it requires the first parameter as an object as key-value pair and second parameter is the union of keys which we need to remove from the object of first parameter.
Similarly Pick and Extract Utility types work.
Lets understand Omit with the example
In the below example, there is Todo interface with four properties. Now we need to make a new type called TodoPreview from Todo interface but it needs only two properties from Todo. So we used Omit to remove “note” & “completed”.
Now TodoPreview will be { title: string; createdAt: number; }
1 2 3 4 5 6 7 8 9 10 11 12 13 |
interface Todo { title: string; note: string; completed: boolean; createdAt: number; } type TodoPreview = Omit<Todo, "note" | "completed">; const todo: TodoPreview = { title: "Hotel", createdAt: 162554425273, } |
5. How to make the type as conditional types in Typescript
Here we will define three types employeeProps , teamLeadProps and dataProps.
dataProps has name property as mandatory along with either employeeProps or teamLeadProps will be required to make the typescript happy if you assign dataProps type to any variable.
Suppose we have a function printData() which accepts the parameter of type dataProps.
Now we can call this function in two ways.
First case – We have to pass three properties in the params. ‘name’ is mandatory. If we pass the designation as ‘associate‘ then we have to pass the mandatory key as nameOfLead.
Second case – In this case also ‘name’ is mandatory and if we pass designation as ‘teamLead’ then it will be mandatory to pass the ‘nameOfManager’ also.
You can see the below example where we have passed the third parameter conditionally on the basis of designation.
This is very useful use case in many scenarios. In many typescript react cases, this conditional typing is required when the parent component needs to pass the props conditionally to its child component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
type employeeProps = { designation: 'associate'; nameOfLead:string; } type teamLeadProps = { designation: 'teamLead'; nameOfManager:string; } type dataProps = { name:string; } & (employeeProps | teamLeadProps ) function printData(params:dataProps){ if(params.designation === 'teamLead'){ console.log(params.nameOfManager) }else{ console.log(params.nameOfLead) } } printData({name:'kai',designation:'teamLead',nameOfManager:'linda'}) printData({name:'Bin',designation:'associate',nameOfLead:'jess'}) |