TypeScript
What is TypeScript
- JavaScript superset
- Support ECMAScript6 standard and output ECMAScript 3/5
The difference between JavaScript and TypeScript
TypeScript is a superset of JavaScript and extends the syntax of JavaScript. Therefore, existing JavaScript code can work with TypeScript without any modification. TypeScript provides static type checking at compile time through type annotation
Install typescript
npm install -g typescript tsc app.ts
Or online typescript compilation website:
Basic data type
- Boolean type
let bool: boolean = false; // js let bool = false;
- number
let num: number = 6 // js let num = 6
- character string
let str: string = 'string' // js let str = 'string'
- array
let list: number[] = [1, 2, 3]; // js let list = [1, 2, 3];
- Tuple tuple
let x: [string, number] = ['hello', 6] // js let x = ['hello', 6];
- Enum enum
enum Direction { NORTH SOUTH EAST WEST } // js var Direction; (function (Direction) { Direction[Direction["NORTH"] = 0] = "NORTH"; Direction[Direction["SOUTH"] = 1] = "SOUTH"; Direction[Direction["EAST"] = 2] = "EAST"; Direction[Direction["WEST"] = 3] = "WEST"; })(Direction || (Direction = {}));
- any
let notSure: any = 4;
- void
Used to identify the type of return value of a method, indicating that the method has no return value.
function hello(): void { alert("Hello Runoob"); } // js function hello() { alert("Hello Runoob"); }
- null
Indicates that the object value is missing.
let n: null = null;
- undefined
let u: undefined = undefined;
By default, null and undefined are subtypes of all types. That is, you can assign null and undefined to variables of type number. However, when you specify the -- strictNullChecks tag, null and undefined can only be assigned to void and their respective values.
- never
Never types represent the types of values that never exist. For example, never type is the return value type of function expressions or arrow function expressions that always throw exceptions or have no return value at all; Variables can also be of type never when they are constrained by type protection that is never true.
// The function returning never must have an unreachable end point function error(message: string): never { throw new Error(message); } // The inferred return value type is never function fail() { return error("Something failed"); } // The function returning never must have an unreachable end point function infiniteLoop(): never { while (true) { } }
- Object
object represents a non primitive type, that is, a type other than number, string, boolean, symbol, null or undefined.
Using object type, you can better represent objects like An API like create. For example:
declare function create(o: object | null): void; create({ prop: 0 }); // OK create(null); // OK
TypeScript assertion
Type assertions take two forms
- Angle bracket syntax
let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length;
- as syntax
let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;
Type guard
Type protection is an expression that performs runtime checks to ensure that the type is within a certain range. In other words, type protection ensures that a string is a string, although its value can also be a numeric value. Type protection is not completely different from feature detection. Its main idea is to try to detect attributes, methods or prototypes to determine how to deal with values. At present, there are four main ways to realize type protection:
- Attribute judgment: in
interface Foo { foo: string; } interface Bar { bar: string; } function test(input: Foo | Bar) { if('foo' in input) { // Here, the input type "tightening" is Foo } else { // Here, the input type "tighten" is Bar } }
- Type judgment: typeof
function test(input: string | number) { if(typeof input == 'string') { // Here, the input type "tighten" is string } else { // Here, the input type "tightening" is number } }
- Instance judgment: instanceof
class Foo {}; class Bar {}; function test(input: Foo | Bar) { if(input instanceof Foo) { // Here, the input type "tightening" is Foo } else { // Here, the input type "tighten" is Bar } }
- Literal equality judgment = =,! =, = =, = ===
type Foo = 'foo' | 'bar' | 'unknown'; function test(input: Foo) { if (input != 'unknown') { // Here, the input type "tightening" is' foo '|' bar ' } else { // Here, the input type "tightening" is "unknown" } }
Advanced type
1. Union Types
If the code base wants to pass in a number or string type parameter, you can use the union type as the padding parameter:
/** * Takes a string and adds "padding" to the left. * If 'padding' is a string, then 'padding' is appended to the left side. * If 'padding' is a number, then that number of spaces is added to the left side. */ function padLeft(value: string, padding: string | number) { // ... } let indentedString = padLeft("Hello world", true); // errors during compilation
If a value is a union type, we can only access members common to all types of this union type.
interface Bird { fly(); layEggs(); } interface Fish { swim(); layEggs(); } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // okay pet.swim(); // errors
- Type protection and differentiation
let pet = getSmallPet(); if ((<Fish>pet).swim) { (<Fish>pet).swim(); } else { (<Bird>pet).fly(); }
Type alias
Type aliases are used to give a type a new name.
type Message = string | string[]; let greet = (message: Message) => { // ... };
Cross type
Cross type is to combine multiple types into one type. This allows us to stack existing types together into one type, which contains all the required types of features.
function extend<T, U>(first: T, second: U): T & U { let result = <T & U>{}; for (let id in first) { (<any>result)[id] = (<any>first)[id]; } for (let id in second) { if (!result.hasOwnProperty(id)) { (<any>result)[id] = (<any>second)[id]; } } return result; } class Person { constructor(public name: string) { } } interface Loggable { log(): void; } class ConsoleLogger implements Loggable { log() { // ... } } var jim = extend(new Person("Jim"), new ConsoleLogger()); var n = jim.name; jim.log();
function
Function definition
// Named function function test() { } // Anonymous function let test = function() {};
Function type
function add(x: number, y: number): number { return x + y; } let myAdd = function(x: number, y: number): number { return x + y; };
Optional parameters
The compiler will verify that the number of parameters passed to a function must be consistent with the number of parameters expected by the function.
In JavaScript, each parameter is optional and can be passed or not. When no parameter is passed, its value is undefined. In TypeScript, we can use it next to the parameter name? Realize the function of optional parameters.
function test(a: string, b?: string) { if(b) { return b } else { return a } }
Optional parameters must follow the required parameters.
Default parameters
function buildName(firstName: string, lastName = "Smith") { return firstName + " " + lastName; } let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
Remaining parameters
Required parameters, default parameters and optional parameters have one thing in common: they represent a parameter. Sometimes you want to manipulate multiple parameters at the same time, or you don't know how many parameters will be passed in. In JavaScript, you can use arguments to access all the parameters passed in.
function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); } let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
Ellipsis is also used on function type definitions with remaining parameters:
function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); } let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
heavy load
array
Data deconstruction
let x: number; let y: number; let z: number; let five_array = [0,1,2,3,4]; [x,y,z] = five_array;
Array expansion operator
let two_array = [0, 1]; let five_array = [...two_array, 2, 3, 4];
Array traversal
Interface
Interface
interface IQuery { page: number; findOne(): void; findAll(): void; }
optional attribute
interface SquareConfig { color?: string; width?: number; }
Read only attribute
interface Point { readonly x: number; readonly y: number; }
Difference between readonly and const
The simplest way to judge whether to use readonly or const is to use it as a variable or as an attribute. Const is used as a variable, and readonly is used as an attribute.
Additional attribute checks
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
perhaps
interface SquareConfig { color?: string; width?: number; [propName: string]: any; }
Function type
In addition to using interfaces to describe object structures, interfaces can also describe function types.
interface SearchFunc { (source: string, subString: string): boolean; }
let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { let result = source.search(subString); return result > -1; }
generic paradigm
In software engineering, we should not only create consistent and well-defined API s, but also consider reusability. Components can support not only current data types, but also future data types, which provides you with very flexible functions when creating large-scale systems.
function identity<T>(arg: T): T { return arg; }
Mode of use
- The first is to pass in all parameters, including type parameters
let output = identity<string>("myString"); // type of output will be 'string'
- The second type inference -- that is, the compiler will automatically help us determine the type of T according to the passed parameters
let output = identity("myString"); // type of output will be 'string'
Generic class
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; }
Generic constraints
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; }
Iterators and generators
Iteratability
When an object implements Symbol.iterator Property, we think it is iterative. Some built-in types such as Array, Map, Set, String, Int32Array, Uint32Array, etc. have implemented their own symbol iterator. Symbol on object The iterator function is responsible for returning values for iteration.