TypeScript is a free and open source programming language developed by Microsoft. It is a superset of JavaScript, and essentially adds optional static typing and class-based object-oriented programming to the language

Or online community about TS is mostly to the understanding of the official document, first introduced from the base type, this doesn’t make any sense to TS have experienced developers, for just enough to fit students proposed to read the official document, most students including me would like to see to solve the problems in the actual project to share.

I’ve been working on TypeScript projects for the last year, and from the initial anyTS to the actual APPLICATION of TS, I’ve come to realize how much BENEFIT TS brings to the project. Even in the maintenance of non-TS projects always feel unnatural, fatigue, dizziness and other symptoms, which is somewhat related to the project, hey hey!

Why use TypeScript

When we used JS to play Happy, we suddenly had to use TS. I was a little nervous from time to time, which increased the learning cost, but also had to step on holes and dig holes. Following his uncle, his two uncle are his uncle, I plucked up courage in the project to do up.

So why use the TS question, if you solve the following question, the answer will come out naturally

Why is JS dynamically typed in type checking

Js is a dynamically typed language because it does not allow variable types to be changed at any time, such as var a = 100; A = ‘ym’, the value of a is a numeric type, and can also be assigned to a string

Why is JS called a weakly typed language

Strong types do not allow implicit conversions, but JS does allow implicit conversions, such as a+ B, where a and B are numeric types and are added together. If either of them is a string, string concatenation is performed, where the numeric type is first toString() converted to a string

Weak types cause problems

function sum(a, b) {
  return a + b;
}
sum(10.10); / / 20
sum(10."10"); / / '1010'

let obj = {};
obj[true] = 100;
console.log(obj["true"]); // 100, object literals will line key.toString ()
Copy the code

Strong type dominance

  • Mistakes are exposed earlier
  • The code is smarter, the code is more accurate
  • Refactoring is more reliable
  • Reduce unnecessary type judgments

For example:

// The type of element is not certain, and may be error, or undefined
function render(element) {
  return elements.name;
}

// The element object has a name string type
interface eleProps {
  name: string;
}
function render1(element: eleProps) {
  return elements.name;
}
Copy the code

Considerations for using enumerated types

Enumerations are worth mentioning, because enumerations invade code, and most interviewers like to ask what enumerations compile into JS

Enumeration types invade code and eventually compile to a two-way key-value object, but defining enumerations using const is removed when compiled

enum Status {
  a,
  b,
}
console.log(Status.a);

// Compile to es5
var Status;
(function (Status) {
    Status[Status["a"] = 0] = "a";
    Status[Status["b"] = 1] = "b";
})(Status || (Status = {}));
console.log(Status.a); / / 0

console.log(Status); // {0: "a", 1: "b", a: 0, b: 1}

enum Status {
  a = "ym",
  b = "yn",}console.log(Status.a);

// Compile to es5
var Status;
(function (Status) {
    Status["a"] = "ym";
    Status["b"] = "yn";
})(Status || (Status = {}));
console.log(Status.a); // ym

console.log(Status); // {a: "ym", b: "yn"}

// Constant enumeration is recommended
const enum Status {
  a = "ym",
  b = "yn",}console.log(Status.a);

// It is recommended to use const enumerations when compiled into ES5 js files
console.log("ym" /* a */);

Copy the code

Application scenarios of enumeration types

The following example does not feel good for one place, but it is more maintainable when used in multiple places

/ / not used
const { caseAllergy, caseOld, caseMarriage } = props;
const getCaseValue = (type: string) = > {
  switch (type) {
    case "caseAllergy":
      return caseAllergy;
    case "caseOld":
      return caseOld;
    case "caseMarriage":
      return caseMarriage;
    default:
      return ""; }};// Use enumeration
enum CaseType {
  caseAllergy = 'caseAllergy',
  caseOld='caseOld',
  caseMarriage='caseMarriage'
}

const { caseAllergy, caseOld, caseMarriage } = props;
const getCaseValue = (type: string) = > {
  switch (type) {
    case CaseType.caseAllergy:
      return caseAllergy;
    case CaseType.caseOld:
      return caseOld;
    case CaseType.caseMarriage:
      return caseMarriage;
    default:
      return ""; }};Copy the code

Function internal parameters take optional arguments

Note that optional parameters are placed after required parameters

function func1(a: number, b? : number, ... rest: number[]) :string {
  return "balabala";
}
Copy the code

Use any type

Any is also required for special occasions, such as stringify

function stringify(value: any) {
  return JSON.stringify(value);
}
// You can do that
function stringify<T> (value: T) :string {
  return JSON.stringify(value);
}
Copy the code

Use of type assertions

Type assertion is like conversion in other languages, but without special data checking and deconstruction. It has no run-time impact, only at compile time.

We use the DOM definition in development, or use Hooks to define state

/ / as syntax
const [callName, setCallName] = useState('user1' as string);

// Get the DOM object
const rootDom = document.getElementById('root') as HTMLElement;

// Angle bracket syntax
const [callName, setCallName] = useState<string>('ym');

React uses as instead of tag
const res = 1;
const num = <number>res;
Copy the code

How do you define object literals

Create an object literal when setting up a cache, storing temporary variables, and so on

// Set the cache
interface CacheProps {
  [prop: string]: string;
}

const cache: CacheProps = {};
cache.foo = "value";
cache.bar = "value2";
Copy the code

interface vs type

A type alias can act like an interface, however, with some subtle differences.

  • In common

Both can be used to describe the type of an object or function

// interface
interface Point {
  x: number;
  y: number;
}
interface PointHandle {
  (x: number, y: number): void;
}

// type
type Point = {
  x: number,
  y: number,
};
type PointHandle = (x: number, y: number) = > void;
Copy the code
  • The difference between

Type aliases can also be used for other types, such as primitive types (primitive values), union types, and tuples

// Basic type
type State = string;
/ / function
type StateFun = () = > string;
// Union type
type UnionState = State | StateFun;
/ / tuples
type Data = [number, string];
Copy the code

Type aliases cannot extends and implements (nor themselves can extends and implements other types).

interface User {
  name: string;
}
interface UserProps extends User {
  userId: number;
}

// Type requires the ampersand character to extend the attribute
type User = { name: string };
type UserProps = User & { userId: number };
Copy the code

Type The mapping type can be generated using the IN keyword. Interface can not be

type Keys = "ym" | "yn"

type NameType = {
  [key in Keys]: string
}

const demo: NameType = {
  ym: "name1".yn: "name2"
}
Copy the code

Class usage considerations

Abstract features describing concrete things, class attributes must be declared before use

class Person {
  public name: string;
  // Private property, cannot be accessed externally
  private age: number;
  Unlike private, members are only allowed to be accessed in subclasses
  protected gender: boolean;
  // Read-only attribute
  readonly sex: string;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  say(msg: string): void {
    console.log(this.name, msg);
  }
  static create(name: string, age: number) {
    return new Person(name, age)
  }
}

class Students = new Person();
const ym = new Person('name1'.20);
Copy the code

The application of interfaces to classes

To enhance interface reusability, public method definitions are extracted

interface Eat {
  eat(food: string): void;
}
interface Run {
  run(distance: number): void;
}

class Person implements Eat.Run {
  eat(food: string): void {
    console.log(food);
  }
  run(distance: number) {
    console.log(distance); }}Copy the code

An abstract class

Use abstract cannot be inherited by new only

abstract class Animal {
  eat(food: string): void {
    console.log(food);
  }
  abstract like(action: string): void
}

class Dog extends Animal {
  like(action: string): void {
    console.log(`${action} The ${this.eat}`); }}const dog = new Dog();
dog.eat('dog food');
dog.like('and');

Copy the code

Handling Event Objects

The React declaration file provides a type declaration for the Event object. The React.ChangeEvent can be used for change and the React.MouseEvent can be used for click

// Mouse events
onClick = (e: React.MouseEvent<HTMLDivElement>) = > {
  // do something
};
// Input change event
onChange = (e: React.ChangeEvent<HTMLInputElement>) = > {
  // do something
};
// Drag events
onChange = (e: React.DragEvent<HTMLDivElement>) = > {
  // do something
};
// Wheel event
onChange = (e: React.WheelEvent<HTMLDivElement>) = > {
  // do something
};
// Clipboard events
onChange = (e: React.ClipboardEvent<HTMLDivElement>) = > {
  // do something
};
Copy the code

Use generics to define functions

// Define a function using generics
function create<T> (length: number, value: T) :T[] {
  const arr = Array < T > (length).fill(value);
  return arr;
}

const res = create <string> (3."foo");
Copy the code

Use generics to define higher-order components

interface IVisible {
  visible: boolean;
}

function withVisible<T> (
  WrapComponent: React.ComponentType<T & IVisible>
) :React.ConponentType<omit<T,"visible"> >{
  return class extends Component<T> {
    render() {
      return <WrapComponent {. this.props} visible={true} />; }}; }Copy the code

The end of the

The TS problems encountered in the project are still being summarized, please pay attention!

Fast development project based on TS+React+Antd

Umi3 + React hooks + DVA + typescript + ANTD

Github.com/hanyueqiang…

Recommended reading

Handwritten React Hooks

Why can’t React use index as key

Elegant use of useRef in React Hooks