一、编译选项

配置文档
文档2
tsc --init

  • outDir: 编译输出目录
  • target: 指定编译的代码版本目标 默认ES3
  • watch: 监听模式,只要文件变更,会自动编译
// 命令行模式`getComputeStyle`
tsc --outDir ./dist --target es6 ./src/helloTypescript.ts
tsc -p ./config/xxx.json  // -p可以指定配置文件目录

配置编译文件tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    "watch":true,
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "umd",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": ["DOM","ESNext","DOM.Iterable"],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. default:false */
    // "checkJs": true,                       /* Report errors in .js files. default:false */
    // "jsx": "preserve",                     /* 在 `.tsx`文件里支持JSX    Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* 生成d.ts文件 Generates corresponding '.d.ts' file.  不能和allowjs同时为true*/
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* 连接并输出到单一个文件中 Concatenate and emit output to single file. 只有module为'amd', 'system'才适用*/
    "outDir": "./dist",                        /*输出文件目录  Redirect output structure to the directory. */
    // "rootDir": "./",                       /* 输入文件的根目录  Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* 将每个文件作为单独的模块(与“ts.transpileModule”类似)Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "baseUrl": "./",                       /* 解析非绝对模块的基础目录 Base directory to resolve non-absolute module names. */
    "paths": {
      // * 类似于alias
      "*":["node_modules/@types","src/typings"]
    },                           /* 模块名到基于 `baseUrl`的路径映射的列表  A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    "rootDirs": [
      // 表示这两个目录中的文件放到同一个目录中
      "src/module",
      "src/core"
    ],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* 要包含的类型声明文件路径列表。List of folders to include type definitions from. */
    // "types": [],                           /* 要包含的类型声明文件名列表。 Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
      
  },
  "files":[],// 要编译的文件路径(不是目录) 优先级 files => include => 根目录 不能用*通配符
  "include": ["./src/**/*"], // 要编译的文件目录或文件
  "exclude": [], // 编译排除的文件目录或文件
  "extends": "" // 基础其它文件,会覆盖
}

二、类型系统

图片.png

1、基础类型

let title: string = "标题";
let n: number = 100;
let isOk: boolean = true;

2、空和未定义类型 Null和undefined

let un: undefined;
un = 1;  // error 只能是undefined
let o: null;
o = 1; // error 只能是null

null和undefined是所有类型的子类型

let a: string = '哈哈';
a = null; // 可以
a = undefined; // 可以
  • 未赋值情况下,值为undefined
  • 同时未声明类型 则是any类型
let b; 

strictNullCheck 会检测null ele是any或者null

let ele = document.querySelector('#box');
const id = ele.id  // error ele可能是null

3、object

let obj: object = {
    x: 1,
    y: 2
}

// object只是告诉obj是一个对象 有.toString等方法,但是没有说明有x属性
obj.x = 3; // error


// 内置对象类型
let d1: Date = new Date();
let st = new Set([1, 2]);


// 包装器类型
// 包装器类型不能赋值给基础类型
let str1 = new String('abc');
str1 = 'def'; // ok
let str2 = 'abc';
str2 = new String('def'); // error

4、数组类型

// 数组类型
let arr1: string[] = [];
arr1.push(1); // error
arr1.push('a'); // ok

// 用泛型表示数组
let arr2: Array<number> = [];

// 元组类型 数组可以存储不同类型数值
// 个数和类型位置都要对应
let arr3: [number, string] = [10, 10]; // error
let arr4: [number, string] = [10, 'aaaa']; // ok

5、枚举类型

// key不能是数值,value可以是数字或字符串,默认是0 1 2 。。。。
enum HTTP_CODE {
    OK = 200,
    NOT_FOUND = 404
}
console.log(HTTP_CODE[200]) // "OK"

// 书写语义化
if (Response.code === HTTP_CODE.OK) {

}

// 接口
enum URLS {
    USER_LOGIN = '/user/login',
    USER_REGISTER = '/user/register'
}

6、void、never

// 无值类型
function fn(): void {
    return 1; // error
}

// never 没有正常执行下去
function fn2(): never {
    throw new Error()
}
let nv = fn2(); // ok nv类型是never
let ay: any = 1;
nv = ay; // error

6、any和unknown

// any类型 不知道数据类型时使用 any就是绕过所有检测
let ay1: any;
ay1 = 1;
ay1 = 'aa'; // ok

let ay2: any = 11;
ay2 = 'aa'; // ok
ay2.a.b.c = 5; // ok

// unknown 安全的any类型
let a1: any;
a1.b.c = 1; // ok
let a2: unknown;
a2.b.c = 2; // error 不会无脑的忽略错误

7、函数类型

let add = function (x: number, b: number): number {
    return x + b;
}
function foreach(data: string[], callback: (a: number, b: string) => void) {
    for (let i = 0; i < data.length; i++) {
        callback(i, data[i])
    }
}
let arr5 = ['a', 'b', 'c'];
foreach(arr5, function () {

})

8、接口interface

interface Point {
    x: number,
    y: number,
    z?: number,  // 可选属性,表示 number|undefined  error 可能是undefined 因为有任意属性,这里就没必要了
    readonly id: number, // 只读属性
    [props: string]: number // 任意属性 方便扩展  x y z也必须是字符串
}

let p: Point;
p = {
    x: 1,
    y: 1,
    id: 234567,
    k: 67890
};
p[1] = 555  // 1也会被转成字符串
p.id = 56789; // error 只读属性,不能修改
  • 接口索引只能是字符串和数字
interface Point2 {
    [props: string]: number,
    [props: number]: number,
}
let p2: Point2 = {};
p2[1] = 1;
p2['a'] = 2;
  • 当同时存在数字和字符串类型索引时 ,数字类型的值必须是字符串类型值得子类型
interface Point3 {
    [props: string]: number,
    [props: number]: string, // error
}
interface Point4 {
    [props: string]: Object,
    [props: number]: string, // ok
}
  • 接口用在函数中
interface Addfun {
    (x: number, y: string): number;
}
type Addfun2 = (x: number, y: string) => number;
const addx: Addfun = (x, y) => {
    return 5
}

interface Counter {
    (): void;
    counter: number;
}

const getCounter = (): Counter => {
    const c = () => { c.counter++ }
    c.counter = 0;
    return c;
}

9、联合类型

function css(ele: Element, attr: string, value: string | number) {}
let box = document.querySelector('.box');
if (box) {
    css(box, 'width', '100px');
    css(box, 'opacity', 1);
}

10、交叉类型

interface o1 {
    x: number;
    y: number;
}
interface o2 {
    z: number;
}

let obj11: o1 = {
    x: 1,
    y: 2
}
let obj22: o2 = {
    z: 3
}
let obj33: o1 & o2 = {
    x: 1,
    y: 2,
    z: 3
}

11、字面量类型

function setPosition(ele: Element, direction: 'left' | 'top') {}
let box1 = document.querySelector('.box');
if (box1) {
    setPosition(box1, 'top')
}

12、类型别名

type dir = 'left' | 'top';
type o3 = o1 & o2;

13、类型推导

let x;  // any
x = 1;
x = 'a';

14、类型断言

let ele1 = <HTMLImageElement>document.getElementById('my');  // Element
let ele2 = document.getElementById('my') as HTMLImageElement;  // Element
console.log(ele1.src)

15、类型操作符

let colors = {
    color1: 'red',
    color2: 'blue'
}

let typeColors = typeof colors; // "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"

type b = typeof colors; // {color1:string,color2:string}
let data: b = {
    color1: 'a',
    color2: 'a'
}

16、keyof操作的是类型

interface Person {
    name: string;
    age: number;
}
type ab = keyof Person;  // 'name' | 'age'
let data2: ab = 'name'

let p1 = {
    name: 'haixing',
    age: 35
}

function getPersonVal(k: keyof typeof p1) {
    return p1[k]
}

function css2(ele: Element, attr: keyof CSSStyleDeclaration) {
    return getComputedStyle(ele)[attr]
}

let box3 = document.querySelector('.box');
if (box3) {
    css2(box3, 'abc')
}

17、in操作符

let ax = 'a' in { a: 3 }
type abc = 'name' | 'age';
type newPerson = { // 添加到新类型
    [k in abc]: string
}
let np:newPerson={name:'a',age:`12`};

18、继承

interface type1 {
    x: number;
    y: string;
}

interface type2 extends type1 {
    z: boolean;
}

let ex1: type2 = { x: 1, y: 'a', z: true };
ex1.x = 5;

19、泛型

interface type1 {
    x: number;
    y: string;
}

// T指定了传参 像Array<string>
function fn4<T extends type1>(args: T) { }
fn4({ x: 1, y: 'a' })
fn4({ x: 1, y: 'a', z: '哈哈' })
fn4({ x: 1, k: 'a' }) // error

20、类型保护

function toUpperCase(arg: string | string[]) {
    console.log(arg.length); // ok
    console.log(arg.toUpperCase()); // error
}
  • 断言
if (!!(<string>arg).toUpperCase) {
    return (<string>arg).toUpperCase()
} else {
    (<string[]>arg).push('aaa')
}
  • typeof也会作为类型检查的依据
if (typeof arg === 'string') {
    return arg.toUpperCase()
} else {
    arg.push('aaa')
}
  • instanceof
if (arg instanceof Array) {
    arg.push('aaa')
} else {
    return arg.toUpperCase()
}
  • 自定义类型保护 关键 xx is type
// 返回这个会被作为类型推断依据
function canEach(data: Element[] | NodeList | Element): data is Element[] | NodeList {
    return (<NodeList>data).forEach !== undefined
}

function fn5(elements: Element[] | NodeList | Element) {
    if (canEach(elements)) {
        elements.forEach(() => { })
    } else {
        elements.classList.add('box')
    }
}
let eles = document.querySelectorAll('.box');
fn5(eles);

lihaixing
463 声望719 粉丝

前端就爱瞎折腾