Tips for using TypeScript


As a superset of JavaScript, TypeScript makes JavaScript development more efficient and maintainable by providing a static type system and support for new features of ES6+. Mastering the skills of using TypeScript can help us better develop and organize JavaScript projects. When I first started using it, I felt that there were a lot of limitations, especially after configuring static type detection, it was easy to report various errors, and I wished to use any. Wouldn’t it become AnyScript, but practice makes perfect, and you will fall in love with this language after using it a lot. Here is a summary of some commonly used ts skills.

skills

When developing with TypeScript, there are some common techniques that can help you improve code quality and development efficiency. Here are some TypeScript usage tips:

  1. Type annotations and type inference: Try to add type annotations to variables, function parameters, function return values, etc. to increase the readability and type safety of the code. At the same time, TypeScript will also automatically infer many types, making full use of the type inference feature.

  2. Use interfaces and type aliases: Use interfaces and type aliases to define custom types, making your code more expressive and clear.

// 使用接口
interface Person {
    
    
  name: string;
  age: number;
}

// 使用类型别名
type Point = {
    
     x: number; y: number };
  1. Generics: Use generics to increase the flexibility of your code, enabling functions and classes to handle multiple types of data.
function toArray<T>(value: T): T[] {
    
    
  return [value];
}
  1. Enumerations: Use enumerations to define a set of constant values ​​with names to improve code readability.
enum Color {
    
    
  Red,
  Green,
  Blue,
}
  1. Non-null assertions and optional chaining: Use non-null assertions (!) to tell the compiler that a value must not be null or undefined, and optional chaining (?.) to simplify handling properties and methods that may be null or undefined.
const name: string = maybeName!; // 非空断言
const age = person?.age; // 可选链
  1. Definite assignment assertion: Use a definite assignment assertion (!) when declaring a variable to tell the compiler that the variable must be assigned a value before it is used.
let value!: number;

TypeScript built-in utility types

When developing with TypeScript, there are some common type tools (utility types) that can help you better handle types, and improve code quality and development efficiency. The following is a detailed explanation in Chinese for Partial, Record, Pick, Omit, Excludeand Parametersthese types of tools:

  1. Partial<Type>(some types):

    • Partialis a type tool built into TypeScript to make all properties of a given type optional.
    • It creates a new type in which Typeall properties of a given type become optional.
    • Example:
    interface Person {
          
          
      name: string;
      age: number;
    }
    
    type PartialPerson = Partial<Person>;
    
    // 等同于:
    // interface PartialPerson {
          
          
    //   name?: string;
    //   age?: number;
    // }
    
  2. Record<Key, Type>(record type):

    • Recordis TypeScript's built-in type tool for creating an object type consisting of a specified key and a given value type.
    • It takes two type parameters Keyand Type, and creates an object type where each property's key is the type Keyand value is the type Type.
    • Example:
    type AgeMap = Record<string, number>;
    
    // 等同于:
    // interface AgeMap {
          
          
    //   [key: string]: number;
    // }
    
  3. Pick<Type, Keys>(select type):

    • PickTypeScript is a built-in type tool used to select specific properties from a given type to form a new type.
    • It takes two type arguments Typeand Keys, and creates a new type that contains only the properties Typeof the type specified by Keys.
    • Example:
    interface Person {
          
          
      name: string;
      age: number;
      address: string;
    }
    
    type PersonNameAndAge = Pick<Person, "name" | "age">;
    
    // 等同于:
    // interface PersonNameAndAge {
          
          
    //   name: string;
    //   age: number;
    // }
    
  4. Omit<Type, Keys>(type omitted):

    • OmitTypeScript is a built-in type tool for omitting specific properties from a given type to form a new type.
    • It takes two type parameters Typeand Keys, and creates a new type that contains all the properties of type Typeexcept those Keysspecified by .
    • Example:
    interface Person {
          
          
      name: string;
      age: number;
      address: string;
    }
    
    type PersonWithoutAddress = Omit<Person, "address">;
    
    // 等同于:
    // interface PersonWithoutAddress {
          
          
    //   name: string;
    //   age: number;
    // }
    
  5. Exclude<Type, ExcludedUnion>(exclusion type):

    • ExcludeExcludedUnionis TypeScript's built-in type tool for excluding members from a given type that can be assigned to .
    • It takes two type parameters Typeand ExcludedUnion, and creates a new type that contains only members of type that Typeare not assignable to ExcludedUnion.
    • Example:
    type MyNumbers = number | string | boolean;
    
    type OnlyNumbers = Exclude<MyNumbers, string | boolean>;
    
    // 等同于:
    // type OnlyNumbers = number;
    
  6. Parameters<Type>(function parameter type):

    • Parametersis TypeScript's built-in type tool for extracting parameter types from a given function type.
    • It takes a function type Typeas an argument and returns a tuple type consisting of the function's argument types.
    • Example:
    type MyFunction = (name: string, age: number) => void;
    
    type FunctionParameters = Parameters<MyFunction>;
    
    // 等同于:
    // type FunctionParameters = [string, number];
    

keyof

In TypeScript, keyofis a keyword and type operator that is used to obtain the union type of all property names of a type. keyofFeatures such as generics and indexed types can be combined to implement many useful type operations.

The syntax for using keyofis keyof Type, where Typeis a type. It returns a union type containing Typethe names of all properties in the type. This union type can be used to access or manipulate Typeproperties in the type. keyof is slightly similar to Object.keys, except that keyof takes the key of interface.

Here is a simple sample code:

interface Person {
    
    
  name: string;
  age: number;
  gender: string;
}

type PersonKey = keyof Person;
// 等同于:type PersonKey = "name" | "age" | "gender"

In this example, keyof Persona union type is returned containing Personthe names of all properties in the type. The result type is "name" | "age" | "gender".

keyofCan be combined with other TypeScript features such as:

  1. Access object properties by index type:
function getProperty<T, K extends keyof T>(obj: T, key: K) {
    
    
  return obj[key];
}

const person: Person = {
    
     name: "Alice", age: 30, gender: "female" };
const name = getProperty(person, "name"); // name的类型是string
  1. Determine if the attribute exists:
function hasProperty<T, K extends keyof T>(obj: T, key: K): boolean {
    
    
  return key in obj;
}

const hasAge = hasProperty(person, "age"); // hasAge的值是true
const hasEmail = hasProperty(person, "email"); // hasEmail的值是false

extends Qualified Generics

In TypeScript, you can use extendsthe keyword to limit the scope of generic types to ensure that the incoming generic parameters meet certain conditions. This approach is called "generic constraint" or "generic qualification". Through generic constraints, we can perform more precise type checking on generics and improve the type safety of the code.

Here are a few extendsexamples of using the keyword to qualify generics:

  1. Simple generic constraints:
function printProperty<T extends {
      
       name: string }>(obj: T) {
    
    
  console.log(obj.name);
}

printProperty({
    
     name: "Alice", age: 30 }); // OK
printProperty({
    
     age: 30 }); // Error: 缺少name属性

In this example, using extends { name: string }to limit the generic Tmust have a nameproperty, otherwise an error will be reported when calling.

  1. Use multiple generic constraints:
function combine<T extends string, U extends string>(a: T, b: U): string {
    
    
  return a + b;
}

const result = combine("Hello, ", "TypeScript"); // result的值是 "Hello, TypeScript"

In this example, use extends stringto restrict the generic type Tand Umust be stringof type to ensure that only stringparameters of type can be passed combineinto function .

  1. Use interfaces to constrain generics:
interface Lengthwise {
    
    
  length: number;
}

function printLength<T extends Lengthwise>(obj: T) {
    
    
  console.log(obj.length);
}

printLength("Hello"); // 输出: 5
printLength([1, 2, 3]); // 输出: 3

In this example, using extends Lengthwiseto qualify the generic Tmust satisfy Lengthwisethe interface, that is, it must have a lengthproperty.

The difference between interface and type

In TypeScript, interfaceand typeare two ways to define types, they have some similarities, but also some differences. Here's how they differ:

  1. interface

    • interfaceis a type declaration used to describe the shape of an object.
    • It can be used to define the structure of an object, including properties, methods, and index signatures.
    • interfaceCan be merged, when defined multiple times with the same name interface, they will be automatically merged into one.
    interface Person {
          
          
      name: string;
      age: number;
    }
    
    interface Person {
          
          
      gender: string;
    }
    
    // 合并后等同于:
    // interface Person {
          
          
    //   name: string;
    //   age: number;
    //   gender: string;
    // }
    
  2. type

    • typeis a type alias used to define any type.
    • It can be used to define primitive types, union types, intersection types, function types, etc.
    • typeCannot be merged, and typean error will be reported when multiple definitions of the same name.
    • To merge need to &connect with
    type Age = number;
    
    type Gender = "male" | "female";
    
    type Person = {
          
          
      name: string;
      age: Age;
      gender: Gender;
    };
     type both = Person & Age // 这样将两个类型合并成一个
    
  3. scenes to be used:

    • interfaceUsually used to describe the structure of objects, it is more suitable for defining types of objects and classes.
    • typeMore complex types can be defined, including union types, intersection types, and function types, etc., which are more suitable for defining temporary type aliases.

Guess you like

Origin blog.csdn.net/study_way/article/details/132087580