DEV Community

Genne23v
Genne23v

Posted on

Advanced Types in TypeScript

Strongly typed languages increase the safety of programs. It doesn't mean that strongly typed languages are always better than weakly typed languages. Weakly typed languages can reduce the development time. So programmers should choose a programming language based on the purpose of the program. Although I contributed some of Typescript projects, but I didn't have much knowledge about Typescript typing. I learned some of very useful typing techniques during Starchart code review.

When using the same type with different property names

You could face the situation that it doesn't make sense to have two different type names while only small portion of the properties varies. My DNS module in Starchart is a good example to explain this instance. At the beginning, we use the variable name as any type of domains. But in our app, this name could be subdomain or fully qualified domain name which can be shortened to fqdn. This is very confusing when writing a code to use the function. You don't have any idea whether you are going to get subdomain or fqdn which could result in a wrong implementation or frustrating the writer to look up all the code to figure what it actually is. So we can do something like this.

type Name = { subdomain: string } | { fqdn: string };
interface BaseDnsRequestData {
  type: string;
  value: string;
}
type DnsRequestData = BaseDnsRequestData & Name;

Enter fullscreen mode Exit fullscreen mode

So DnsRequestData can have either subdomain or fqdn. When you extract the data, Typescript knows what type is passing only in runtime. So you should extract the data as below.

let name;
if ('subdomain' in data) {
  name = data.subdomain;
} else {
  name = data.fqdn;
}
Enter fullscreen mode Exit fullscreen mode

When type naming is not necessary

Sometimes it's better not to name the type when passing data is obvious or varying similar names is more confusing. So you can instead of defining as below,

interface Record {
  type: string;
  name: string;
  value: string;
  description: string;
  ports: string;
}

type DnsRequestData = {
  type: Record['type'];
  name: Record['name'];
  value: Record['value'];
  description?: Record['description'];
  ports?: Record['ports'];
}
Enter fullscreen mode Exit fullscreen mode

You can simplify the type without naming.

Pick<Record, 'type' | 'name' | 'value'> & Partial<Pick<Record, 'description' | 'ports'>> 
Enter fullscreen mode Exit fullscreen mode

Conclusion

It was really good for me not just to learn these techniques, but also to help me to write better code. It seems not important for someone who develops something quickly, but typing is very important when many contributors or developers are working together. It finds the potential errors quickly and gives an idea of what this code does. It also takes a lot of learning from the experienced. I never thought about this kind of problems when I was working alone. Having the experienced developers' feedback is really helpful to learn how to write better code. Thanks for reading my article!

Top comments (0)