TypeScript学习笔记——基础篇

类型推论

如果没有明确指定类型,typescript会根据类型推论的规则推断出一个类型。
注意:
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断为any类型而完全不被类型检查

联合类型

联合类型表示取值可以为多种类型中的一种。
使用| 来分隔类型
示例代码:

let myFavoriteNumber: string | number;

注意:
当不确定一个联合类型的变量到底是哪个类型的时候,只能访问此联合类型的所有类型共有的属性和方法。

接口

  • 赋值的时候,变量的形状必须和接口的形状保持一致
  • 可选属性使用?
  • 任意属性:使用 [propName: string]定义了任意属性取 string 类型的值。
interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}

注意:

  1. 定义来任意属性后,确定属性和可选属性的类型必须是任意属性类型的子集
  2. 如果同时存在任意属性、可选属性,那么任意属性的数据类型要带undefined
  • 只读属性readonly
    注意: 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:

数组的类型

  • 类型[]表示法
let fibonacci: number[] = [1, 1, 2, 3, 5];
  • 可以使用数组泛型来表示数组
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
  • 用接口表示数组(过于复杂,一般不用)
interface NumberArray {
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

NumberArray表示:只要索引的类型是数字时,那么值的类型必须是数字

可以用接口来描述类数组:

function sum() {
    let args: {
        [index: number]: number;
        length: number;
        callee: Function;
    } = arguments;
}

数组里any的使用
表示数组中允许出现任意类型

let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];

函数的类型

两种常见的定义函数的方式:

  • 函数声明
function sum(x: number, y: number): number {
    return x + y;
}
  • 函数表达式
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

注意:
TypeScript的类型定义中,=>用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
在 ES6 中,=>叫做箭头函数.

用接口定义函数的形状

interface SearchFunc {
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}

关于函数的参数:

扫描二维码关注公众号,回复: 11516092 查看本文章
  • 可选参数后面不允许再出现必需参数
  • 添加了默认值的参数会被识别为可选参数,不受前面☝️第一条限制

示例代码:

function buildName(firstName: string = 'Tom', lastName: string, nickName?: string) {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat', 'mimi');

重载:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

注意:
TypeScript会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

类型断言

类型断言可以用来手动指定一个值
使用语法:
值 as 类型 (建议使用as语法,不容易混淆)或 <类型>值

注意: 类型断言只能够「欺骗」TypeScript编译器,无法避免运行时的错误。小心使用!

使用场景:
判断传入的参数是不是ApiError类型

interface ApiError extends Error {
    code: number;
}
interface HttpError extends Error {
    statusCode: number;
}

function isApiError(error: Error) {
    if (typeof (error as ApiError).code === 'number') {
        return true;
    }
    return false;
}

如上,因为接口是一个类型,不是一个真正的值,它在编译结果中会被删除,就无法使用 instanceof来做运行时判断,此时就只能使用类型断言来判断。

将类型断言为any

window.foo = 1;

上述代码,在TS编译时会报错,显示window上不存在foo属性
将window断言为any类型,则可以运行:

(window as any).foo = 1;

any类型的变量上,访问任何属性都是允许的。

注意: 将类型断言为any,是我们解决问题的最后一个手段。(在类型的严格性和开发的便利性之间掌握平衡)

类型断言总结:

  1. 联合类型可以被断言为其中一个类型
  2. 父类可以被断言为子类
  3. 任何类型都可以被断言为any
  4. any可以被断言为任何类型

由第3,4点,产生了双重断言,形式如as any as Foo, 了解了解,不要使用

注意:

  • 类型断言只会影响TS编译时的类型,类型断言语句在编译结果中会被删除。它不会影响到变量的类型,若要进行类型转换,直接使用类型转换方法。
  • 类型声明比类型断言更加严格(优先使用类型声明)
const tom = getCacheData('tom') as Cat;  // 类型断言
const tom: Cat = getCacheData('tom');    // 类型声明
  • 可以使用泛型来更加规范的实现对类型的约束

声明文件

  • declare var声明全局变量
  • declare function 声明全局方法
  • declare class 声明全局类
  • declare enum 声明全局枚举类型
  • declare namespace 声明(含有子属性的)全局对象
  • interfacetype 声明全局类型
  • export 导出变量
  • export namespace 导出(含有子属性的)对象
  • export default ES6 默认导出
  • export =commonjs 导出模块
  • export as namespace UMD 库声明全局变量
  • declare global 扩展全局变量
  • declare module 扩展模块
  • /// <reference /> 三斜线指令

内置对象

  • ECMAScript标准提供的内置对象有:Boolean Error Date RegExp
  • DOM和BOM提供的内置对象有:Document, HTMLElement Event NodeList
  • TypeScript 核心库的定义文件中定义了所有浏览器环境需要用到的类型,并且是预置在 TypeScript 中的。

注意: TypeScript 核心库的定义中不包含 Node.js 部分。想要使用,需要引入第三方声明文件

npm install @types/node --save-dev

类型别名

类型别名用来给一个类型起个新名字,常用于联合类型。

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}

字符串字面量类型

字符串字面量类型用来约束取值只能是某几个字符串中的一个

type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
    // do something
}

handleEvent(document.getElementById('hello'), 'scroll');  // 没问题
handleEvent(document.getElementById('world'), 'dblclick'); // 报错,event 不能为 'dblclick'

// index.ts(7,47): error TS2345: Argument of type '"dblclick"' is not assignable to parameter of type 'EventNames'.

注意: 类型别名与字符串字面量类型都是使用 type 进行定义。

猜你喜欢

转载自blog.csdn.net/weixin_40693643/article/details/107496168