TypeScript Advanced Type Inferences

TypeScript Advanced Type Inferences

TypeScript offers a rich set of tools for crafting custom types. We can define new types, build upon existing ones through inheritance, and even use generics to create types that adapt to a variety of data. These features, when combined, empower us to create sophisticated type definitions. We can define types that depend on others, or that are based on a subset of another type's properties. We can even reshape a type by adding or removing properties as needed.

In this article, we'll delve into more advanced type inference techniques.


Type aliases give us a way to name and reuse complex type definitions. But they become truly powerful when we bring generics into the mix, letting us build types dynamically based on other types. If we add the keyof keyword to the mix, we gain the ability to create new types that are specifically based on the properties of another type.

interface IRequired {
  a: number;
  b: string;
}

// Create a variable ab that conforms to the IAbRequired interface
let ab: IRequired = {
  a: 1,
  b: "test",
};

// Define a generic type WeakInterface that makes all properties of a given type optional
type WeakInterface<T> = {
  [K in keyof T]?: T[K];
};

// Create a variable allOptional of type WeakInterface<IRequired> and initialize it as an empty object
let allOptional: WeakInterface<IRequired> = {};        

Note that even though we are making each property in the type?IRequired?optional, we can’t define properties that are not available on this original type.


Partial Mapped Types

The?WeakType?type alias that we created earlier is actually called?"Partial". Constructs a type with all properties of?Type?set to optional.

type Partial<T> = {
 [P in keyof T]?: T[P];
};

// Example
interface User {
  id: number;
  name: string;
  email: string;
}

const updateUser = (user: User, updates: Partial<User>): User => {
  return { ...user, ...updates };
};

const user: User = {
  id: 1,
  name: "John Doe",
  email: "[email protected]",
};

const updatedUser = updateUser(user, { name: "Jane Doe" });

console.log(updatedUser); 
// Output: { id: 1, name: "Jane Doe", email: "[email protected]" }        

Required Mapped Types

There is also a mapped type named?"Required" which will do the opposite of?Partial?and mark each property as required:

type Required<T> = {
    [P in keyof T]-?: T[P];
};

// Example
interface User {
  id: number;
  name?: string;
  email?: string;
}

const getUserInfo = (user: Required<User>): void => {
  console.log(`ID: ${user.id}, Name: ${user.name}, Email: ${user.email}`);
};

const user: Required<User> = {
  id: 1,
  name: "John Doe",
  email: "[email protected]",
};

getUserInfo(user);

// ? ERROR: Missing required properties
const invalidUser: Required<User> = { id: 2 }; 
// Type '{ id: number; }' is missing the following properties from type 'Required<User>': name, email        

Readonly Mapped Types

Similarly, we can use the?Readonly?mapped type to mark each property as?readonly?as follows:

type Readonly<T> = {
 readonly [P in keyof T]: T[P];
};        

Picked mapped Types

The?Pick?mapped type is used to construct a type based on a subset of properties of another type.

interface IAbc {
  a: number;
  b: string;
  c: boolean;
}

// Define a new type PickAb using the Pick utility type to select only the "a" and "b" properties from the IAbc interface.
type PickAb = Pick<IAbc, "a" | "b">;
let pickAbObject: PickAb = {
  a: 1,
  b: "test",
};        

Record Mapped Types

The?Record?mapped type, which is used to construct a type on the fly. This type is essentially the inverse of the Pick mapped type. Instead of choosing specific properties, it requires a defined set of properties, specified as string literals, to be present in the type.

type RecordedCd = Record<"c" | "d", number>;

// Declare a variable of type RecordedCd and assign it an object with properties "c" and "d"
let recordedCdVar: RecordedCd = {
  c: 1,
  d: 1,
};
        

Omit Mapped Types

Constructs a type by picking all properties from?Type?and then removing?Keys

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
}

// Create a type that excludes "password"
type PublicUser = Omit<User, "password">;

const user: PublicUser = {
  id: 1,
  name: "John Doe",
  email: "[email protected]",
  // password: "secret123" // ? ERROR: Property 'password' does not exist on type 'PublicUser'.
};

console.log(user);        

TypeScript's advanced type inference capabilities, particularly the combination of type aliases, generics, and the keyof keyword, provide developers with a powerful toolkit for crafting highly expressive and maintainable type systems. By leveraging these features, we can move beyond simple type definitions and create complex, dynamic types that accurately reflect the structure and behavior of our data. For a full comprehensive list of the different types you can make checkout TypeScript Utility section. https://www.typescriptlang.org/docs/handbook/utility-types.html





要查看或添加评论,请登录

Andrew Pettigrew的更多文章

  • The AWS CDK Guide to Create your own Amazon Cognito User Pool and Client

    The AWS CDK Guide to Create your own Amazon Cognito User Pool and Client

    Amazon Cognito User Pool is a user directory for web and mobile app authentication and authorization. A user pool…

  • The Complete Guide to Implement AWS Cognito using Amplify with NextJS

    The Complete Guide to Implement AWS Cognito using Amplify with NextJS

    This guide will cover how to implement prebuilt authentication flows with AWS Cognito and Next.js 14 using your own…

    1 条评论
  • Getting Started with Cloud Computing

    Getting Started with Cloud Computing

    Do you need a quick understanding of the cloud, what it is, how it works, and what’s it made up of? This primer on…

  • Value Proposition Design

    Value Proposition Design

    Have you ever thought about why you buy from one company versus another? Think about two businesses that are doing the…

  • Evolution of The Web 1.0 - 3.0

    Evolution of The Web 1.0 - 3.0

    The web is the primary tool used by billions of people all over the world, who use it to browse, read, write and share…

    2 条评论
  • What is Product Management

    What is Product Management

    Originally posted here: What is product mangement? Who are product managers? What do they even do? Do you need them?…

  • How to be more productive with Trello + Google Calendar in 2021

    How to be more productive with Trello + Google Calendar in 2021

    Introduction Disclaimer: This might not work for you and as such, you may need to find an alternative solution that…

  • The Development of a NFC Mobile Application for JUTC

    The Development of a NFC Mobile Application for JUTC

    In light of my previous post Managing JUTC Public Wifi, I felt some youthful exuberance to go back in the archives of…

    2 条评论
  • Managing JUTC Public Wifi

    Managing JUTC Public Wifi

    Introduction In this post, I'll be going over a project my team and I under took this year, 2020. This project was…

    1 条评论
  • Intro to RESTful API

    Intro to RESTful API

    What is RESTful API REST is an acronym for Resist Eating Stale-food Today..

社区洞察

其他会员也浏览了