null和undefined类型:
是所有类型的子类型,即可以将任意类型赋值为二者
any类型:
可以赋值任何类型
unknown类型:
引入的顶级类型unknown,对照于any,unknown是类型安全的,任何值都可以赋给unknown
(1)赋值给其他类型:当没有类型断言或基于控制流的类型细化时unknown不可以赋值给其它类型,除了它自己和any外。
let v:unknown;
let s:string=v; 报错
(2)操作unknown类型:在unknown没有被断言或细化到一个确切类型之前,是不允许在其上进行任何操作的。
除了:==/===/!==操作
(3)unknown与其他类型的交叉类型都是其他类型
除了any
(4)unknown与其他类型的联合类型都是unknown
除了any
(5)never是unkonw的子类型
keyof unkonw的结果是never
(6)类型映射中keyof的是unknown类型,则不会映射任何类型
type aaa = {
[P in keyof T]:T[P]
}
type g=aaa 结果:type g = {}
object类型:
除了number等基础类型以外的类型(String等也属于object类型),Object类型才包括所有类型
基本变量类型
let 变量名:类型
HTMLElement:
单个dom元素类型
NodeList:
dom列表类型,如document.querySelectorAll返回的dom集合
event事件类型:
event:MouseEvent
文档碎片类型:
const fragment: DocumentFragment = document.createDocumentFragment()
never类型
用作返回值:
function xx():never{
never表示函数无法执行完成
如:
throw new Error();
或while(true){...}
}
用作参数:
传入约定之外(不可得到的类型)的类型
function xx(x:never):never{throw new Error()};
function yy(p:string){
xx(p);
}
yy([1,2,3])
枚举类型(定义后不能修改)
enum x {XX1,XX2=num,...}
(1)未设置值,x.XX1=0,后面值增序排列,若值是表达式,则后面的枚举成员必须设置初始值
(2)若设置值,则设置了值的后面未设置值的数据按照设置值增序排列
(3)反向映射:x[num]为对应的XX,若设置了值,x[值]为对应的XX
(4)枚举类型可以数字和字符串组合,字符串枚举之后必须赋值
enum x {
a:1, 编译阶段运行
b:'aa',
c:'cc'.length, 执行阶段运行
}
(5)当枚举成员未赋初值或初值为字符串或数值,则枚举成员成为一种类型约束,即约束变量只能为其枚举类型
枚举成员为number类型,可以赋值number类型,不同枚举成员不能赋值即使是相同类型
枚举成员为字符串类型,只能赋值枚举成员,不能赋值字符串
enum ShapeKind {
Circle,
Square,
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
let c: Circle = {
kind: ShapeKind.Square, 错误,类型为ShapeKind.Circle
}
(6)常量枚举,编译阶段被删除(直接替换成对应的值,删除生成的对象),避免在额外生成的代码上的开销和额外的非直接的对枚举成员的访问
const enum x{...}
(7)枚举联合类型
enum x{...}
let y:x=只能是枚举成员
联合类型
let 变量名:类型1|类型2
使用的方法/属性必须是两种类型共有的
类型断言(绕过类型检查,如可添加约束类型外的参数等,类似强制转换,但只在编译时期)
用来指定一个值的类型,使得一个多种类型的变量能使用各自类型的特有方法/属性
方式一:
(<类型>变量名)
(<类型1|类型2>变量名)
方式二:
(xx as 类型) 每个相同变量前都需要添加
当as之后的类型为对象时,前面的类型必须包含有后面类型的属性,或者as any
方式三:
if( 'xx属性' in 对象/类){...}
方式四:
if(typeof 变量==='类型'){...} 只能判断string、number、boolean、symbol类型
方式五:
if(变量 instanceof 类){...}
方式六(类型谓词):
创建一个函数,使用类型谓词 parameterName is Type这种形式,parameterName必须是来自于当前函数签名里的一个参数名。
function isJava(lang: Java | JavaScript): lang is Java { 必须是类型谓语,不能是boolean返回值,因为类型谓语发生在编译时,会有类型断言效果,返回boolean发生在运行时,无类型断言效果,分支语句会报错
return (lang).helloJava !== undefined;
...
返回的只要是能判断类型的布尔值
如:return typeof lang==='string'
}
代码示例:
enum Type { Strong,Week }
class Java {
helloJava(){
console.log(" Hello Java ")
}
java: any
}
class JavaScript {
helloJavaScript() {
console.log('Hello Javascript')
}
javascript: any
}
function isJava(lang: Java | JavaScript): lang is Java {
return (lang).helloJava !== undefined;
}
function getLanguage(type: Type, x: string | number){
let lang = type === Type.Strong ? new Java() : new JavaScript()
if (isJava(lang)) {
lang.helloJava()
} else {
lang.helloJavaScript()
}
}
方式七:赋值类型断言("strictNullChecks": false未开启的情况下)
假定不会出现null和undefined,则变量!的方式使用
变量!从变量的类型里去除了 null和 undefined
方式八:可辨识联合类型
满足两个条件:
(1)每个类型具有唯一的单例属性,如字符串字面量、数字或symbol值
(2)使用类型别名将这些类型联合起来
(3)若要使用完整性检查,即每个类型对应的分支都要写出来
方式一:开启strict或strictNullChecks,为函数指定返回值
方式二:定义捕捉函数,放到分支最后
function error(params:never):never { 当进入到最后一个分支,会因为参数类型和never不匹配报错
throw new Error('缺少分支');
}
例子:
interface a{
king: 1,
size:number
}
interface b{
king: 2,
height: number,
width: number;
}
interface c{
king: 'c';
radius: number;
}
type d = a | b | c;
function t(s: d):number {
if (s.king == 1) { 也可以换成switch
return s.size;
} else if (s.king == 2) {
return s.height
} else {
return s.radius
}
}
类型兼容
对象:
当检查类型时,只会检查是否满足必要属性,多余属性不检查
interface Named {
name: string;
}
let x: Named;
let y = { name: 'Alice', location: 'Seattle' };
x = y; 可以赋值,函数参数同理
函数:
参数列表不同:
要查看x是否能赋值给y,首先看它们的参数列表.x的每个参数必须能在y里找到对应类型的参数.注意的是参数的名字相同与否无所谓,只看它们的类型.这里,x的每个参数在y中都能找到对应的参数,所以允许赋值。
let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // OK
x = y; // Error
返回值不同:
类型系统强制源函数的返回值类型必须是目标函数返回值类型的子类型。
let x = () => ({name: 'Alice'});
let y = () => ({name: 'Alice', location: 'Seattle'});
x = y; // OK
y = x; // Error, because x() lacks a location property
可选参数、固定参数和不定参数两两兼容(在参数类型和返回结果相同情况下)
函数重载:
function a(num:string):string 1
function a(num:number):number 2
function a(num:any):any{
return num;
}
let x=a; x的类型为{1,2},再次赋值的函数重载函数必须也具有1、2类型
枚举:
枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的。比如
enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };
let status = Status.Ready;
status = Color.Green; // Error
类
类有静态部分和实例部分的类型,比较两个类类型的对象时,只有实例的成员(属性和方法)会被比较(比较类型而非结果)。
如果目标类型包含一个private/protected成员, 这允许子类赋值给父类,但是不能赋值给其它有同样类型的类。
class Animal {
feet: number;
constructor(name: string, numFeet: number) { }
}
class Size {
feet: number;
constructor(numFeet: number, s: number) { } 构造器参数写成private x:类型,则不兼容
static num:any;
}
let a: Animal;
let s: Size;
a = s; // OK
s = a; // OK
泛型:
泛型类型对结果无影响时兼容
interface Empty {
}
let x: Empty;
let y: Empty;
x = y; // OK, because y matches structure of x
interface NotEmpty {
data: T;
}
let x: NotEmpty;
let y: NotEmpty;
x = y; // Error, because x and y are not compatible
没指定泛型类型时兼容
let identity = function(x: T): T {
// ...
}
let reverse = function(y: U): U {
// ...
}
identity = reverse; // OK, because (x: any) => any matches (y: any) => any
内置对象
let b:Boolean=new Boolean(1)
Bom和Dom类型
HTMLElement
NodeList
父类型:event 子类型MouseEvent
函数返回值
function xx():类型{
void无返回值
...
}
类型推论:
未声明类型变量且未赋值可以变成任意类型,相当于any
let me;
未声明类型变量赋了值,只能使用值的类型
let me='123'
数组类型:
let arr=[1,2,3]; 任意类型值
let arr2:类型[]=[...]; let arr2:类型1[]|类型2[]=[...]; let arr2:(类型1|类型2)[]=[...];
let arr3:Array<类型>=[...]; let arr3:Array<类型1|类型2>=[...];
let arr4:ReadonlyArray<类型>=[...]; 只读数组
元组:
多种类型元素的数组
let arr:[类型1,类型2]=[元素,...] 值和类型以及类型的数量必须对应
接口定义数组
interface arr4{
[index:number]:类型; 索引为数值,值为指定数值的数组
}
let arr5:arr4=[1,2,3];
解构赋值
const b={id:1,name2:true};
const {id:number,name2:string}=b;
const {id:i,name2:n}:typeof b=b; i、n对结果无影响
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210225153043707.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzI5NDU2MA==,size_16,color_FFFFFF,t_70)
代码示例:
let flag:boolean=true;
let bool:boolean=Boolean(1); //也会创建布尔变量,如果使用new Boolean()将会报错,此时为布尔对象
let num:number=1;
let nnum:number=NaN; //NaN也是number数值类型
let nnnnum:number=Infinity; //无限大数值类型
let uname:string='jeff';
//函数返回值
function hello():void{
console.log('hello')
}
let kong:void=undefined; //undefined和null为空值
let kong2:void=null;
let un:undefined=undefined; //undefined和null可以互相切换,他们是一切类型的子类型
let nn:null=null;
//任意值类型
let me:any='abc';
me=123;
//未声明类型且未赋值,会被默认为任意值类型
let mm;
mm=12;
mm='哈哈';
//未声明类型但赋了值,会被认为是值的类型,不能改变成其他类型
let aa='123';
//联合类型
let cat:string|number;
cat='me';
cat=1;
//断言
function f(x:number|string){
if((<string>x).length)
{
return (<string>x).length
}
}
//数组
let arr=[1,2,3];
let arr2:number[]=[1,2,3];
let arr3:Array<number>=[1,2,3];
interface arr4{
[index:number]:number; //索引为数值,值为数值的数组
}
let arr5:arr4=[1,2,3];