TS 文档自学 - 记录1

学习文档 : https://wangdoc.com/typescript/intro
学习阮一峰大神的TS,编写边记录重点。全文均已 TypeScript 教程为准。

简介

1.概述: TS 是 JS的超集(superset),是一个独立的类型系统。
2.概念:一组具有相同特征的值。类型是人为添加的一种编程约束合用法提示,可以帮助开发人员在开发过程中,得到更多的验证。提高代码质量,减少错误。
3. 类别:
动态类型 - JS,弱类型,可以随时更改数据类型
动态类型 - TS,不可改变类型
4. 优点:TypeScript 有助于提高代码质量,保证代码安全,更适合用在大型的企业级项目
《1. 有利于代码的静态分析,开发阶段运行静态检查,发现问题,降低线上风险。
(代码的静态分析:根据类型,不必运行代码,就可以确定变量的类型,从而推断代码有没有问题。)
《2. 有利于发现错误。
《3. 有更好的IDE支持,做到语法提示跟自动补全。
《4. 有代码文档(typedoc)
《5. 有助于代码重构
5. 缺点:兼容性问题、不一定适合那些小型的、短期的个人项目
《1. 丧失了动态代码的灵活性。
《2. 增加了编程工作量。
《3. 更改的学习成本
《4. 独立的编译步骤
《5. 兼容性问题

基础用法

  1. 类型声明:一律为在标识符后面添加“冒号 + 类型”。函数参数和返回值,也是这样来声明类型。
let foo:string;
变量 foo 后使用**冒号**,声明了类型为**string**
function toString(num:number):string{
	return String(num)
}
函数toString()的参数num的类型是number。参数列表的圆括号后面,声明了返回值的类型是string

** TypeScript 规定,变量只有赋值后才能使用,否则就会报错
  1. 类型推断
    TypeScript 会自己推荐类型。
let foo = 123;
变量 foo 并么有声明类型,由于他被赋值为一个数值,此时 ts 推荐 foo 的类型为 number。如果后面将 foo 改为其他类型的值,跟推断的不一样,ts 会报错。
foo = 'hello'; //报错

ts 也可以推断返回值
function toString(num:number){
	return String(num)
}
toString() 没有声明类型,ts 推断为字符串。因为ts的类型推断,所以**函数返回值的类型通常是省略不写的**

ts 的设计思路,类型声明是可选的,你可以加,也可以不加。不加类型声明,依然是有效的ts代码,只是不能保证正确的推断出类型。这也是 js 代码都是合法的ts 代码的原因。

  1. TS的编译
    ts -> js 的过程 叫做编译(compile)。
    ts 官方只提供编译器。
    ts 的类型检查只是编译时的类型检查,代码编译为js 后,运行时不会在检查类型了。

  2. 值与类型
    值:value 类型:type
    “类型” 是针对 ”值” 的,“类型”是“值”的一个元属性。每一个值在TS里都是有类型的。比如, 3 是一个值,他的类型是 number
    ts 只涉及类型。
    ts项目包括两种代码:底层的“值代码”和上层的“类型代码”。“值代码” - > js 语法,“类型代码” -> ts 语法。
    可以分离。ts编译过程实际是把“类型代码”全部拿掉,只保留“值代码”。

  3. TypeScript Playground:官方的在线编译页面。

  4. tsc 编译器:官方编译器。ts脚本的后缀名:.ts,tsc 就是将 .ts 脚本转变成 .js

6.1 安装 npm install -g typescript 版本:-v
6.2 帮助信息 -h --all
6.3 编译脚本 tsc app.ts 生成一个 app.js 的脚本文件。 tsc 1.ts 2.ts 3.ts 4.ts 编译多个
–outFile 将多个ts 编译成一个js : tsc file1.ts file2.ts --outFile app.js
–outDir 参数可以指定保存到其他目录。 tsc app.ts --outDir dist 会在 dist 生成 app.js
–target tsc --target es2015 app.ts 可以编译支持不同版本的 js
6.4 编译错误的处理 (tsc 命令的更多参数,详见《tsc 编译器》一章)
6.5 tsconfig.json
将 编译参数 写在配置文件 tsconfig.json 里。
{ "files":["1.ts","2.ts"], "compilerOptions":{ "outFile":"dist/app.js" }}
有了配置文件,编译时直接调用 命令就行: tsc

  1. ts-node 模块 非官方的 npm 模块,可以直接运行ts代码。
    简单运行ts代码看效果, ts-node 是一个便捷的方法
全局安装ts-node  
npm i -g ts-node
运行
ts-node script.ts

直接输入 tsc 不带参数 会给一个大于号,此时进入了 ts 的 REPL运行环境。可以逐步输入代码运行。
$ ts-node
> const twice = (x:string=> x+x;
> twice('abc')
'abcabc'
> .exit

不安装 ts-node 
npx ts-node script.ts  
npx 在线调用 ts-node

any 类型,unknown 类型,never 类型

any 类型 - “顶层类型”(top type),涵盖了所有下层。
  1. 含义:any 类型表示没有任何限制,该类型的变量可以赋予任意类型的值。设置为any时,ts实际上会关闭这个变量的类型检查,只要句法正确,都不会报错。
  2. 类型推断问题:
    《1. tsc --noImplicitAny xxx.ts 打开该选项,推断出any 类型就报错。
    《2. let var 声明的变量,打开noImplicitAny,不赋值,不指定类型 不报错,建议用 const
  3. 污染问题:污染其他具有正确类型的变量,把错误留到运行时。
unknown 类型 - 类型不确定,严格版的 any。‘顶层类型’,除any以外其他类型的全集。
  1. 跟 any 一样,所有的类型的值都可以分配给unknown类型。
  2. 跟 any 不同,不能直接使用。
let v:unknown = 123;
let v1:boolean = v; // 报错
let v2:number = v; //  报错
v 是 unknown 类型,赋值给anyunknown 以外的类型都会报错。这样就避免了污染问题。
  1. 不能直接调用 unknown 类型变量的方法和属性。
let v1:unknown = {foo:123};
		v1.foo //  报错  
let v2:unknown = 'hello'; 
		v2.trim() // 报错
let v3:unknown = (n=0)=>n+1;
		v3() // 报错
直接调用 unknown 类型变量的属性 和 方法 ,或者直接当做函数执行,都会报错
  1. unknown 类型变量能够进行的运算是有限的。
    《1. 比较运算(== 、=== 、!= 、!== 、|| 、&& 、?)
    《2. 取反运算(!)
    《3. typeof
    《4. instanceof
  2. 使用 unknown 类型变量。 -> ‘类型缩小’ ,缩小 unknown 变量的类型范围,确保不会出错。
never类型:空类型->类型为空,不包含任何值。 – ‘底层类型’(bottom type)
let x:server;
x 的类型是never,不可能赋给它任何值,否则都会报错。
  1. 使用场景:类型运算之中,保证类型运算的完整性。
  2. 不可能返回值的函数,返回值的类型就可以写成never
  3. 变量有多种类型(联合类型)。处理所有可能的类型之后,剩余的情况就属于 never 类型。
  4. 特点:可以赋值给任意其他类型。
function f():never{
	throw new Error('Error');
}
let v1:number = f(); //不报错
let v2:string = f(); //不报错
let v3:boolean = f(); //不报错
函数 f() 会抛出错误,所以返回值类型可以写成never,即不可能返回任何值。
  1. never 类型可以赋值给其他类型的原因:跟集合论有关系,空集是任何集合的自己。

总之,TypeScript 有两个“顶层类型”(any和unknown),但是“底层类型”只有never唯一一个。

类型系统

基本类型
  1. 概述:js 类型
    · boolean
    · string
    · number
    · bigint ----?
    · symbol ----?
    · object
    · undefined
    · null
    ts 继承了 js 的类型设计,以上八种可以看做 ts 的基本类型。
    注意:上面所有的类型名称都是小写字母,首字母大写的 Number、String、Boolean 等在JS语言中都是内置对象,不是类型名称。

  2. boolean 类型:true 和 false 两个布尔值。

  3. string 类型:包含所有的字符串

  4. number 类型:包含所有整数和浮点数

  5. bigint 类型:包含所有的大整数

const x:bigint = 123n;
const y:bigint = 0xffffn;
**bigint 与 Number 类型不兼容**
**bigint 类型的值 不能是整数和小数**
**注意,bigint 类型是 ES2020 标准引入的。如果使用这个类型,TypeScript 编译的目标 JavaScript 版本不能低于 ES2020(即编译参数target不低于es2020)。**
  1. symbol 类型:包含所有的 Symbol 值(需看一下 《Symbol》一章)
  2. object 类型:包含了所有的对象、数组和函数。
const x:object = { foo:123 };
const y:object = [1,2,3]; 
const z:object = (n:number) => n+1;
  1. undefined 类型,null类型。
    《1. undefined :包含一个值undefined,表示未定义(即还未给出定义,以后可能会有定义)。
let x:undefined = undefined;
	上述 第一个undefined 是 “类型” ;第二个undefined 是 ”值”

《2. null : 包含一个值 null, 表示为空(即此处没有值)。

**注意,如果没有声明类型的变量,被赋值为undefinednull,在关闭编译设置noImplicitAny和strictNullChecks时,它们的类型会被推断为any**

// 关闭 noImplicitAny 和 strictNullChecks
let a = undefined; // any
const b = undefined; // any
let c = null; // any
const d = null; // any

如果希望避免这种情况,需要打开编译选项:strictNullChecks。
// 打开编译设置 strictNullChecks
let a = undefined; // undefined
const b = undefined; // undefined
let c = null; // null
const d = null; // null
打开编译设置strictNullChecks以后,赋值为undefined的变量会被推断为undefined类型,赋值为null的变量会被推断为null类型。

包装对象类型
  1. 包装对象的概念:
    1.1 原始类型(primitive value):最基本的,不可再分的值。
    特殊值:undefined 和 null
    符合类型:object
    · boolean
    · string
    · number
    · bigint
    · symbol
    以上五种为原始类型,都有对应的包装对象(wrapper object)。所谓“包装对象”,值得是这些值在需要时,会自动产生的对象。
	'hello'.charAt(1) // 'e'
	字符串 hello 执行了 charAt() 方法。但是在JS中,只有对象才有方法。原始类型的值本身没有方法。上述代码运行,是因为在调用方法时,字符串会自动转为包装对象, charAt() 方法其实是定义在包装对象上。
	以上五种包装对象中,symbol类型和bigint类型无法直接获取他们的包装对象( 即Symbol()Bigint(),不能作为构造函数使用),剩下的三种可以:
	· Boolean()
	· String()
	· Number() 
	以上三个构造函数,执行后可以直接获取某个原始类型值的包装对象。
	**三个构造函数只有当做构造函数使用时(即带有 new 命令调用),才会返回包装对象。**
  1. 包装对象类型与字面量类型
    因为包装对象的存在,导致每个原始类型的值都有包装对象和字面量 两种情况。
'hello'; // 字面量
new String('hello');// 包装对象
两个都是字符串。
区分:
· Boolean 和 boolean
· String 和 string
· Number 和 number
· Bigint 和 bigint
· Symbol 和 symbol

大写类型同时包括包装对象和字面量两种情况
小写类型只包含字面量
const s1:String = 'hello'; //正确
const s2:String = new String('hello'); // 正确

const s3:string = 'hello';// 正确
const s4:string = new String('hello'); // 报错

建议使用小写类型。因为绝大部分使用原始类型的场合,都是使用字面量,不适用包装对象。而且 TS 把很多内置方法的参数,定义为小写类型,使用大写类型会报错。

注意:目前在TS里面,symbol 和 Symbol 两种写法没有差异,bigint 和 Bigint 也是如此,建议始终使用 小写的。
Object 类型与 object 类型
  1. Object 类型
    广义对象 - 所有可以转化对象的值,都是Object 类型,这囊括了几乎所有的值。
let object:Object;  // || object:{};
object = true;
object = 'hi';
object = 1;
object = { foo :123 };
object = [1,2];
object = (a:number)=>a +1;
原始类型值、对象、数组、函数都是合法的 Object 类型。除了 undefinednull 以外,其他任何值都可以赋值给 Object 类型。

简写形式:{}   //空对象
  1. object 类型
    狭义对象 - 可以用字面量表示的对象 ,只包含对象、数组和函数,不包括原始类型的值。
let object:object;  // || object:{};
object = { foo :123 }; // 对象
object = [1,2]; // 数组
object = (a:number)=>a +1; // 函数

// 原始类型值  报错
object = true; // 报错
object = 'hi'; // 报错
object = 1; // 报错

大多数时候,我们使用对象类型,只希望包含真正的对象,不希望包含原始类型,所以建议都使用小写。
** 无论大写还是小写,都只包含JS内置对象原生的属性和方法,不包括自定义在这两种类型里的属性和方法。
undefined 和 null 的特殊性
  1. undefined 和 null 即是值,又是类型。
  2. 作为值:任何其他的类型的变量都可以赋值为 undefined 或 null。
let age:number = 24;
age = null;
age = undefined;
JS 的行为是,变量如果等于 undefined 就表示还没有赋值;如果等于 null 就表示值为空。
所以 TS 允许了任何类型的变量都可以赋值为这两个值。
但是 当下编译不报错,运行时会报错。 undefined   不是对象,没有包含对象方法。

解决:
 tsc --strictNullChecks app.ts 打开 --strictNullChecks 选项,undefinednull 就不能赋值给其他类型的变量(anyunknown 类型 除外)。
在 tsconfig.json 配置
{
	"compilerOptions":{
		"strictNullChecks":true
	}
}
** 打开后,undefinednull 两种值也不能相互赋值了。只能赋值给自身,或者any类型和unknown 类型。
值类型
  1. 定义:单个值也是一种类型,成为 ‘值类型’。let x:‘hello’; x 的类型就是 字符串 ‘hello’
  2. const 没有注明类型,就会推断该变量是值类型。
联合类型
  1. 定义:多个类型组成的一个新类型,使用符号 | 表示。(A|B,可以属于A,也可以属于B)
let x:number|string;
x = 123;
x = 'abd'
// x 既可以是数字 也可以是 字符串 ,联合类型值的多少,表达了变量的取值范围有多少。
// 联合类型可以包含 空值
let aa:string|null;
aa = '2sr3'
aa = null
  1. 类型缩小(type narrowing):区分值的类型,进行下一步处理。
    typeof | switch
  2. 联合类型本身是一种 ‘类型放大’(type widening),所以处理时就需要 ‘类型缩小’(type narrowing)
交叉类型
  1. 定义:多个类型组成的一个新类型,用 & 表示。(A&B,同时属于A和B)
  2. 用途:表示对象的合成。为对象类型添加新属性
type A = { foo:number }
type B = A & { bar:number }
type 命令
  1. 定义:定义一个类型的别名。(就是给类型起了一个“艺名”)
  2. 优点:让类型的名字更有意义,增加代码的可读性,便利的使用复杂类型,方便修改变量类型。
  3. 重点:别名不允许重名。
  4. 别名的作用域是块级作用域。
  5. 别名支持表达式
  6. 别名允许嵌套
typeof 运算符
  1. 一元运算符,返回一个字符串,代表操作数的类型。
  2. 操作数 是一个值
  3. JS 只可能返回八种结果,都是字符串
  4. TS返回不是字符串,是 当前值的 TS 类型,只能用在类型运算之中,不能用在值运算。
  5. TS typeof 参数只能是标识符
  6. TS typeof 参数不能是类型
块级类型声明
  1. 类型可以声明在代码块(大括号)里面,并且只在当前代码块有效。
类型的兼容
  1. 某些类型可以兼容其他类型
  2. 子类型(subtype):类型A的值可以赋值给类型B,A 就成为B的子类型。
  3. 凡是可以用父类型的地方,都可以使用子类型,但是反过来不行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值