picture

I have used TypeScript for a year, and the technology used in the project is Vue + TypeScript. I deeply feel the necessity of TypeScript in medium and large-scale projects, especially in large-scale projects with a long life cycle, TypeScript should be used.

The following are the TypeScript tricks that I often use in my work.

1. Notes

The TS type can be marked with a comment in the /** */form of , and the editor will have a better prompt:

/** This is a cool guy. */
interface Person {
  /** This is name. */
  name: string,
}

const p: Person = {
    name'cool'
}

This is a good way to add comments or friendly hints to a property.

picture
picture

2. Interface inheritance

Like classes, interfaces can also inherit from each other.

This allows us to copy members from one interface to another, allowing for more flexibility in splitting interfaces into reusable modules.

interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;

An interface can inherit multiple interfaces to create a composite interface of multiple interfaces.

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

3. interface & type

There are two ways to define types in TypeScript: interfaces and type aliases.

For example, in the following example of Interface and Type alias, except for the syntax, the meaning is the same:

Interface

interface Point {
  x: number;
  y: number;
}

interface SetPoint {
  (x: number, y: number): void;
}

Type alias

type Point = {
  x: number;
  y: number;
};

type SetPoint = (x: number, y: number) => void;

And both are extensible, but the syntax is different. Also, note that interfaces and type aliases are not mutually exclusive. Interfaces can extend type aliases and vice versa.

Interface extends interface

interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }

Type alias extends type alias

type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };

Interface extends type alias

type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }

Type alias extends interface

interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };

The difference between them can be seen in the picture below or in TypeScript: Interfaces vs Types.

picture

So it is not easy to use interface & type skillfully.

If you don't know what to use, remember: use interface if you can, use type if you can't.

4. typeof

typeofOperators can be used to obtain the type of a variable or object.

We generally define the type first, and then use:

interface Opt {
  timeout: number
}
const defaultOption: Opt = {
  timeout500
}

Sometimes it can be reversed:

const defaultOption = {
  timeout500
}
type Opt = typeof defaultOption
picture

When an interface always has a literal initial value, this way of writing can be considered to reduce repeated code, at least two lines of code, right, haha~

5. keyof

TypeScript allows us to iterate over properties of a certain type and extract the name of its property via the keyof operator.

The keyof operator, introduced in TypeScript 2.1, can be used to get all keys of a certain type, and its return type is a union type.

keyofObject.keysSimilar to , except that keyoftakes interfacethe key of .

const persion = {
  age3,
  text'hello world'
}

// type keys = "age" | "text"
type keys = keyof Point;

When writing a method to get the property value in the object, most people may write it like this

function get1(o: object, name: string{
  return o[name];
}

const age1 = get1(persion, 'age');
const text1 = get1(persion, 'text');

But it will show an error

picture

Because there is no pre-declared key in the object.

Of course, if you o: objectchange to o: anyIt will not report an error, but the obtained value will have no type, and it will become any.

picture

At this time, you can use keyofto strengthen getthe type function of the function. Interested students can look at _.getthe typemark and implementation of

function get<T extends objectK extends keyof T>(o: T, name: K): T[K{
  return o[name]
}
picture

6. Find Type

interface Person {
    addr: {
        city: string,
        street: string,
        num: number,
    }
}

When the type of addr needs to be used, in addition to the type

interface Address {
    city: string,
    street: string,
    num: number,
}

interface Person {
    addr: Address,
}

is acceptable

Person["addr"// This is Address.

for example:

const addr: Person["addr"] = {
    city'string',
    street'string',
    num2
}
picture

In some cases the latter makes the code cleaner and easier to read.

7. Find Type + Generics + keyof

Generics (Generics) refers to a feature that does not specify a specific type in advance when defining a function, interface or class, but specifies the type when it is used.

interface API {
    '/user': { name: string },
    '/menu': { foods: string[] }
}
const get = <URL extends keyof API>(url: URL): Promise<API[URL]> => {
    return fetch(url).then(res => res.json());
}

get('');
get('/menu').then(user => user.foods);
picture
picture

8. Type Assertion

In Vue components, ref is often used to obtain the properties or methods of subcomponents, but it is often impossible to infer what properties and methods exist, and an error will be reported.

Subassembly:

<script lang="ts">
import { Options, Vue } from "vue-class-component";

@Options({
  props: {
    msgString,
  },
})
export default class HelloWorld extends Vue {
  msg!: string;
}
</script>

Parent component:

<template>
  <div class="home">
    <HelloWorld
      ref="helloRef"
      msg="Welcome to Your Vue.js + TypeScript App"
    />

  </div>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import HelloWorld from "@/components/HelloWorld.vue"// @ is an alias to /src

@Options({
  components: {
    HelloWorld,
  },
})
export default class Home extends Vue {
  print() {
    const helloRef = this.$refs.helloRef;
    console.log("helloRef.msg: ", helloRef.msg); 
  }

  mounted() {
    this.print();
  }
}
</script>

Because this.$refs.helloRefis an unknown type, an error message will be reported:

picture

Just make a type assertion:

  print() {
    // const helloRef = this.$refs.helloRef;
    const helloRef = this.$refs.helloRef as any;
    console.log("helloRef.msg: ", helloRef.msg); // helloRef.msg:  Welcome to Your Vue.js + TypeScript App
  }

But type anyassertion is not good. If you know the specific type, it is better to write the specific type, otherwise it seems pointless to introduce TypeScript.

9. Explicit Generics

$('button') is a DOM element selector, but the type of the return value can only be determined at runtime. In addition to returning any, you can also

function $<T extends HTMLElement>(id: string): T {
    return (document.getElementById(id)) as T;
}

// 不确定 input 的类型
// const input = $('input');

// Tell me what element it is.
const input = $<HTMLInputElement>('input');
console.log('input.value: ', input.value);
picture
picture

Functional generics don't necessarily have to automatically deduce the type, sometimes it's better to specify the type explicitly.

10. DeepReadonly

readonlyProperties marked with can only be assigned at declaration time or in the class constructor.

It will then be immutable (ie read-only property), otherwise a TS2540 error will be thrown.

constVery similar to in ES6 , but readonlycan only be used on properties in classes (or interfaces in TS), which is equivalent to gettera settersyntactic sugar for properties that only have no .

The following implements readonlya type:

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

const a = { foo: { bar22 } }
const b = a as DeepReadonly<typeof a>
b.foo.bar = 33 // Cannot assign to 'bar' because it is a read-only property.ts(2540)
picture
picture
w3cschool programming lion
Websites dedicated to learning programming


At present, the WeChat customer service number: w3cschool programming lion-qiqi (bcshi666) has an upper limit on the number of friends. I am sorry for the students who have sent friend requests to the customer service but failed!
If you want to ask questions, you can add w3cschool programming lion-tingting (w3cschool66) or scan the code↓ to add.

picture