美文网首页
typescript基础

typescript基础

作者: mao77_ | 来源:发表于2020-04-12 18:00 被阅读0次

1. 目标

1). 了解typescript是什么

TypeScript是JavaScript的一个超集, 主要提供了类型系统和对ES6的支持,由Microsoft开发,开源。

2). 学会typeScript的基本使用
3). 理解typeScript的基本概念

2. 安装TypeScript

npm install -g typescript
编译TypeScript文件
tsc hello.ts

3. 基础

1). 原始数据类型
布尔值、数值、字符串、空值、Null和Undefined

/**
* 布尔值
*/
let isDone: boolean = false;
// 使用构造函数Boolean创建的对象不是布尔值
// let createdByNewBoolean1: boolean = new Boolean(1); // 错误示范

// Type 'Boolean' is not assignable to type 'boolean'.
//   'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.

let createdByNewBoolean2: Boolean = new Boolean(1); // 正确示范
// 或者直接调用Boolean也可以返回一个`boolean`类型:
let createdByNewBoolean3: boolean = Boolean(1);

/**
* 数值
*/
let decLiteral: number = 7;

/**
* 字符串
*/
let myName: string = 'Tom';
let myAge: number = 25;

// 模板字符串
let sentence: string = `Hello, my name is ${myName}.I'll be ${myAge + 1} years old next month.`;

/**
* 空值
*/
function alertName(): void {
alert('Hello typeScript')
}
// 可赋值为undefined或null
let unusable: void = undefined;

/**
* Null和Undefined
*/
let u: undefined = undefined;
let n: null = null;
// 与void的区别是:
// undefined和null是所有类型的子类型。(所有类型皆可如此赋值), 如:
let num: number = undefined;
// 而void类型的变量不能赋值给number类型的变量。
let u1: void;
let num1: number = u;
// Type 'void' is not assignable to type 'number'.

2). 任意值
用来表示允许赋值为任意类型

1> 声明一个变量为任意值之后,对它的任何操作,返回的内容的类型也都是任意值

let anyThing: any = 'Tom';
anyThing.setName('Jerry');
anyThing.setName('Jerry').sayHello();
anyThing.myName.setFirstName('Cat');

2> 若变量在声明时,微指定其类型,也未进行赋值,那么会被识别为任意类型,如:

let something; // 等价于:let something: any
something = 'seven';
something = 7;
something.setName('Eloise');

3). 类型推论
若未明确指定类型,则ts会依据类型推论的规则(当前赋值)推断一个类型

4). 联合类型
1> 当联合类型的变量未赋值时,ts不确定到底是哪个类型的时候,只能访问此联合类型的所有类型里共有的属性或方法:

/* function getLength(st: string | number): number {
  return st.length; // length不是string和number的共有属性,因此会导致报错,报错如下:
  // index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
  // Property 'length' does not exist on type 'number'.
} */
// 正确示范:
function getString(st: string | number): string {
  return st.toString();
}

2> 当联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型

let b: string | number;
b = 'eloise'; // 推断为string类型
console.log(b.length); // 6
b = 7; // 推断为number类型
// console.log(b.length); // 编译报错,如下:
// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.

5). 对象的类型--接口
在ts中,使用接口(Interfaces)来定义对象的类型

// 例子
// 接口一般首字母大写
// 定义的变量比接口多/少一些属性是不允许的
// 赋值的时候,变量的形状必须是和接口的形状保持一致的
interface Person {
name: string;
age: number;
}

let tom: Person = {
name: 'Tom',
age: 25
};

/**
* 可选属性(该属性可以不存在)
* 不要完全匹配一个形状的时候使用
* 但是仍然不允许添加未在接口中定义的属性
*/
interface Person1 {
name: string;
age?: number;
}
let tom1: Person1 = {
name: 'Tom',
age: 25 // 可以不存在
}

/**
* 任意属性
* 注意:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
*/
// ???存在疑问,tsc编译此处并未进行报错,怀疑是ts版本已更新,而我所阅读的文档未进行更新
interface Person2 {
name: string,
age?: number;
[propName: string]: any;
}
let tom2: Person2 = {
name: 'Tom',
age: 15, // 存在疑问,本应报错,实际并没有
gender: 'male',
}

/**
* 只读属性
* 只读的约束存在于第一次给对象赋值的时候, 而不是第一次给只读属性赋值的时候
*/
interface Person3 {
readonly id: number;
name: string,
age?: number,
[propName: string]: any
}
let tom3: Person3 = {
id: 77,
name: 'Tom',
gender: 'male'
}

// tom3.id = 888; // 会报错,如下:
// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

6). 数组的类型
有多种定义方式:
1> 「类型 + 方括号」表示法
2> 数组泛型
3> 用接口表示数组
4> 类数组
5> any 在数组中的应用

/**
* 「类型 + 方括号」表示法
*/
let fibonacci: number[] = [1, 1, 2, 3, 5];

/**
* 数组泛型(Array Generic)
* Array<elemType>
*/
let fibonacci1: Array<number> = [1, 2, 3, 4, 5];

/**
* 用接口表示数组
*/
interface NumberArray {
// 只要索引的类型是数字时,那么值的类型必须是数字
// 过于复杂,一般少用
// 但是常用来表示类数组
[index: number]: number;
}
let fibonacci2: NumberArray = [1, 2, 3, 4, 5]

/**
* 类数组(Array-like Object)
*/
function sum() {
// let args: number[] = arguments; // 会报错
}
// Type 'IArguments' is missing the following properties from type 'number[]': pop, push, concat, join, and 24 more.
// arguments是类数组,不可用普通数组方式来描述

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

// 内置对象:事实上常用的类数组都有自己的接口定义,如:IArguments, NodeList, HTMLCollection等。
function sum2(){
let args: IArguments = arguments
}
/*
interface IArguments {
  [index: number]: any;
  length: number;
  callee: Function;
}
*/

/**
* any在数组中的应用
* 用any表示数组中允许出现任意类型
*/
let list: any[] = ['eloise', 77, {website: 'http://www.baidu.com'}]


7). 函数的类型

函数是js中的一等公民

// 在JavaScript中,有两种常见的定义函数的方式
// 函数声明(Function Declaration)
function sum(x, y) {
  return x + y;
}
// 函数表达式(Function Expression)
let mySum = function (x, y) {
  return x + y;
}

// 在ts中,需要对类型做定义,无论输入值还是输出值
function sum1(x: number, y: number): number {
  return x + y;
}
// sum1(1, 2, 3); // 输入多余的(或者少于要求的)参数,是不被允许的
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.

/**
 * 函数表达式
 */
// mySum2编译不会有问题。但是,只对等号右侧的匿名函数进行了类型定义
// 而等号左边的mySum2,是通过赋值操作进行类型推论而推测出来的
let mySum2 = function (x: number, y: number): number {
  return x + y;
}
// 如果需要手动给mySum2添加类型
// ts的类型定义中,=>用来表示函数的定义,=>左边是输入类型,需要括号括起来,=>右边是输出类型
let mySum3: (x: number, y: number) => number = function (x: number, y: number): number {
  return x + y;
}

/**
 * 重载
 * 重载允许一个函数接受不同数量或类型的参数时,作出不同处理
 */
// 利用联合类型, 缺点是不够精准表达输入类型 === 输出类型
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('');
  }
}
// 精确定义
// 使用重载重新定义多个reverse的函数类型
// 函数定义
function reverse1(x: number):number;
function reverse1(x: string):string;
// 函数实现
function reverse1(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('');
  }
}

8). 类型断言
可以用来手动指定一个值的类型
语法:
值 as 类型

<类型>值
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即值 as 类型
类似<Foo>的语法在tsx中表示的是一个ReactNode,在ts中除了表示类型断言之外,也表示一个泛型
因此使用类型断言,统一建议使用值 as 类型的语法。
正常使用情况下,需要彼此一方对另一方有兼容,则可以去进行断言

9). 声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。

  • 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 /> 三斜线指令
// 三斜线指令,使用场景:
// 1. 当我们在书写一个全局变量的声明文件时
// 2. 当我们需要依赖一个全局变量的声明文件时

10). 内置对象

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

4. 未整理笔记

词汇解析
超集:当有集合A、B,

1> 若B中有的元素,A全部都有,元素相同。则:
A为B的超集, B为A的子集 ( B ⊆ A )

2> 若B中有的元素,A全部都有,并有多于B的元素。则:
B为A的真子集( B ⊂ A )

5. 总结

  1. typeScript是javaScript的超集
  2. typeScript增加了代码的可读性和可维护性(大部分函数看类型定义就能明了如何使用)
  3. 方便快速定位错误(如:代码补全,类型错误,返回值问题,接口提示等。)
  4. 多人/团队开发、或需复用性代码,建议使用typeScript

6. 待解决问题

  1. typeScript中的泛型、元组等这些是指什么?
  2. 如何和框架结合使用(如在vue中如何表现)

相关文章

网友评论

      本文标题:typescript基础

      本文链接:https://www.haomeiwen.com/subject/fzsbmhtx.html