// 小object 代表的是非原始类型 的类型 也就是不能是string number boolean symbol 严格模式 多包括null undefined
let obj1: object = 3; // 报错
let obj2: object = "3"; // 报错
let obj3: object = true; // 报错
let obj4: object = null; // 报错
let obj5: object = undefined; // 报错
let obj6: object = Symbol(); // 报错
let obj7:object = {a: 1, b: '2'};
let obj8:object = [1, 2, 3];
// 非原始类型 object Object 大小的区别
let obj:{} = {name:"张三",age:50};
let obj1:{name:string;age:number}
obj=obj1; //会报错 因为obj是空对象{}
//解决 1.把obj :后面的{} 去掉
// 2. 通过修改类型约束解决
obj1=obj as { name: string; age: number }; 通过修改类型约束解决
let obj2:{} =2
obj2=[] //此时 这个对象的key是obj2 =后面跟着的才是value值 后面的覆盖前面的了
//大写 Object
let obj3:Object=3;
obj3={name:"",age:0};
obj=[] //没有问题 大写Object只是往里面存
//小写object
let obj4:object;
object=4; //会报错 因为不了{}类型
object={a:10,b:20}
//总结 Object是object子类型
export {} // 导出 意思只在该模块区域有效
let arr:Array=[1,2,3];
let arr2:number[]=[10,20,30] //这两者没有区别 意思是一样的 数组里面有number
//元组类型
let arr3:[number,number]=[10,20];
arr3.push(3);
// arr3[2]=2; 会报错 没有索引2的位置
//接口
interface IArray {
[key:number]:V ; //如果是在数组里 key代码是索引 :V是数组里面的值
}
let arr4:IArray[number]=[10,20,30]
//type 类型别名
type ArrType={[key:number]:Object} //后面的Object相当于any 在Ts里面尽量不要给any
let arr5:ArrType=[1,2,3,4,[],{}]
export {};
//字面量类型
let num: "hello";
// num=2 不可以 num的类型就是"hello" 这个"hello"就是字面量类型
//解决 联合类型
let str1:"hello" | number;
str1=1;
str1="hello";
//交叉类型 赋值前后两个类型都要满足
let a:number & string ; //狗都不这样写
//any 什么类型都可以
let a:any = 1;
a="字符串"
// unknown也是可以放任何类型 只是限制这个类型的方法
let b:unknown =1;
b:"字符串"
b.toFixed(2) //会报错 unknown 会进行类型检测
//解决1
if(typeof b =="number"){
b.toFixed(2);
}
//解决2
(b as number).toFixed(2)
//接口 对象类型
interface IObject {
name:string;
age:number;
}
//重命名接口 不会覆盖 只会添加
interface IObject {
gender:string
}
let obj:IObject;
obj={
name:"张三",
age:10,
gender:"蓝孩子"
}
//数组类型
interface IArr {
[key:number]:string; //[]里面的是索引 :跟着的是数据里面的值
}
let arr:IArr=["张三","李四"];
//函数类型
interface FnItf {
(name:string:age:number)=>void; //返回值是void 意思是空 什么都可以 不约束
}
let fn:FnItf=()=>{
return "1" //返回值不受影响
}
//约束的形参必须有两个设置好的类型
fn("张三",30)
export {};
//接口类型 有两种(只读,可缺省)
interface NameItf {
readonly name:string; //只读 仅供读取 不可修改
}
interface AgeItf {
age:number | undefined;
}
//接口类型 继承上面两个接口
interface PersonItf extends NameItf,AgeItf {
//可缺省 可写 可不写
height?:string;
}
let obj:PersonItf;
obj={
name:"",
age:undefined
}
//只读属性 仅供读取 不可修改
// obj.name="张三" 会报错
obj={
name:"",
age:123,
height:"" //最后一个可写可不写
}
//数据改名 或者
type NumType = number | string;
let a:NumType = 1;
a="";
// 函数改名 void返回值是空 就是什么都可以
type FnType = ()=>void;
let fn:FnType;
fn=function(){};
//数组改名 [索引] 外面是组组的值
type ArrType ={[index:number]:NumType};
let arr:ArrType=[2,"张三"]
//对象改名 ?可写可不写
type Object ={name?:string;age?:number};
let obj:Object;
obj={}
//类型别名不能重名 接口interface可以
type Object ={} //会报错 重复使用
//接收interface不能够直接使用联合类型和交叉类型
interface | NumType | FnType |Object //会报错 不能使用联合类型 和交叉类型
//别名类型可以使用
type newType = NumType | FnType | ArrType | Object | PersonItf ;
function fn(p1:number):void{}
function fn1(p1:number):string{
return "我想返回就返回什么 因为没有约束"
}
//type别名 interface 都可以限定函数类型
//可选参数用的 一般可选参数放在后面 放在前面会报错
function fn2(p1:number,p2:string){}
fn2(1,"");
fn2(1)//会报错
//设置默认值
function fn3(p1:string = ""){}
fn3();
// ...arr接收剩余的参数 这个[]里面有number这个数据
function fn4(...arr:number[]){
for(let i=0;i
function fn(){
console.log(this)
}
fn();//指向外层作用域 this没有指向 都是继承过来的
//apply方法 和call方法 bind方法
fn.apply({name:"张三"},[1,2,3]) //apply方法 参数只能传[数据] 和字符串 立即调用
fn.call({name:"李四"},111) //什么都可以传 立即调用
fn.bind(a,10)() //需要自调用
//new操作符都做了什么
//new操作符的返回值 是看函数内的返回值决定的 如果返回的是对象 函数 就可以拿到这个对象 函数如果返回不是对象 函数哪么外面 拿到的是内部创建的对象
export {};
type ObjType = { myname: string };
// 将this指向ObjTyep 或Window 1、此时会报错 原因:当前作用域中没有window 需要在全局设置window属性
function person(this: ObjType | Window, myname: string) {
this.myname = myname;
}
//3.调用Window时需要小写
window.person = person;
window.person("")//因为设置了调用这个函数时需要传入一个字符串
//4.
let obj:ObjType={
myname:"张三"
}
//5.使用person方法
person() // 会报错 因为this指向不是Object类型的变量 而ts中没有window 只有浏览器才有
//解决
person.call(obj,"123")
//设置一个接口 注意:设置接口时要首字母大写 使用的时候需要小写
interface Window {
myname:string;
person:(name:string)=>void
}
export {}
//enum 枚举 将参数枚举成后台的返回值
enum StateCode {
Success=200,
TokenErr = 400,
LoginErr=500
}
let res ={
code : 0
}
//请求判断
if(res.code === StateCode.Success){
//成功
}else if (res.code === StateCode.TokenErr) {
// 失败
} else if (res.code === StateCode.LoginErr) {
// 登录失效
}
js中的else if 真正的样子是 只是帮我们省略了{}号
else{
if{}
else {
if{}
}
}
泛型指的是类型参数化 即将原来某种具体的类型进行参数化 设计泛型的目的在于有效约束类型成员之间的关系 比如函数参数和返回值,类或者接口成员和方法之间的关系
export {};
// 泛型:类型参数化 E 是如果有传来的参数就设置 没有就设置默认的string
interface ArrItf {
[index: number]: E;
}
// 前面的T是形参 V也是只不过V设置了默认值 后同的T|V是接收前面的参数
type NumAndStrAndBool = number | string | boolean | T | V;
let arr: ArrItf = [1, 2, 3];//传入了类型 所以是number[] 就是[里面有number]
let arr1: ArrItf = ['1', '2'];//没有传 默认是string[]
let arr2: ArrItf>=[12] // 自己看吧 联合类型太多
let res = {
code: 0,
data: [{ name: '' }],
msg: '成功',
};
Promise.resolve(res).then((resurl)=>{
console.log(resurl);
if(resurl){} //直接调用是允许的 因为Promise后面直接跟着成功的回调函数 是立即执行的
})
//类型约束
type DataType = { name: string }[];
type ResType = { code: number; data: D };
type PromiseType = Promise>;
function fnData():PromiseType{//通过泛型可以 .点出来数据
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(res);
}, 2000);
});
}
fetchData().then((res) => {
console.log(res);
if (res.code) {//此时直接调用会报错 因为没有传参数类型 和上面的不一样 需要设置泛型
}
});
面向对象实践OOP编程思想 在实际工作中 都是极其有用的抽象 封装利器
export {};
calss Person {
name:string;
age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age
}
}
let p = new Person("张三",18)
console.log(p.name,p.age,p.getName());
使用extends 关键字实现继承 继承上面的Person
class Male extends Person {
height: string;
constructor({ name, age, height }: { name: string; age: number; height: string; }) {
super(name, age); //通过super继承父类的方法和数据
this.height=height
}
}
let m = new Male({ name: "浩达", age: 50, height: "170" });
console.log(m.age, m.name, m.getName(), m.height);
m.getName()
在TypeScript 中就支持3种访问修饰符 分别是public、private、protected。通过这三个修饰符做到控制属性和方法的访问。
public :基类 、子类、 类外部 都可以访问 默认是就是public
protected :基类 子类 可以访问 , 类外部不可以访问
private :基类可以访问 , 子类、类外部不可以访问
readonly: 只读属性 只可获取 不可修改
class Person {
public readonly name: string = '张三';
protected age: number = 20;
private height: string = '180';
protected getPersonInfo():void {
console.log(this.name, this.age, this.height); // 基类里面三个修饰符都可以访问
}
}
class Male extends Person {
public getInfo():void {
console.log(this.name, this.age); // 子类只能访问public、protected修饰符的
}
}
let m = new Male();
console.log(m.name); // 类外部只能访问public修饰的
m.name = '李四'; // name属性使用只读修饰符,所以不能对name进行赋值修改操作
基于静态属性的特性 往往会把与类相关的常量 不依赖实例this上下文的属性和方法定义为静态属性 从而避免数据冗余 进而提升运行性能
// 静态属性 static
class Person {
static gender:string="蓝孩子"
}
//静态属性可以通过类名 去获取 不用再new了
console.log(Person.gender)
抽象类 它是一种不能被实例化仅能被子类继承的特殊类
export {};
//abstract 抽象
abstract class Person {
abstract name:string;
abstract getName():void;
fn(){
console.log("普通方法")
}
}
new Person();// 会报错 不可以通过new创建抽象类的实例
//创建抽象类的方法
class Male extends Person {
name!: string; // ! 变量初始化先不用赋值
getName(): void {
this.name = '张三';
console.log(this.name);
}
}
//抽出来之后 再使用new创建实例
let m = new Male();
m.getName();
console.log(m.name);
m.fn();
//也可以把抽象出来的实例 用作接口使用
let obj: Male;
obj = {
name: '',
fn() {},
getName() {},
};
接口 interface 也可以约束类的实现 使用接口与使用抽象类相比 区别在于接口 只能定义类成员的类型
export {};
// implements 是类接口的一种索引 必须要使用到这条索引才可以使用接口
interface PersonItf {
height: string;
getName: () => string;//这个函数的返回值是string
}
// 类实现接口 implements
class Person implements PersonItf {
name: string = '张三';
age: number = 0;
height: string = '';
getName(): string {
return this.name;
}
}
class Male implements PersonItf {
height: string = '';
getName(): string {
return '';
}
}
extends关键字判断泛型参数p是否string或者是number 其中的一种 最终类型的确定由三无运算的结果 决定
// extends判断前面的类型是否属于后面的类型
type TypeFn = P extends string | number ? string[] : number;
let m: TypeFn = 1; //如果不是直接返回一个number
let m1: TypeFn = ['1', '2']; //是当前类型 就返回number[]
Required 可以设置必填 之前 设置的? 可填可不填 当设置了Required之后 就一定要填了 因为把 ? 删除了
export {};
interface PersonItf {
name?: string; // ? 可填可不填
age?: number;
height: string;
}
let p1: PersonItf;
p1 = {
height: "",//这里没有设置 所以可以不填
};
// Required 设置里面的属性都是必填的
type PersonType = Required;
let p2: PersonType;
// 现在约束的数据是必须要填的
p2 = {
name: "",
age: 0,
height: "一米七",
};
类型推断 infer相当于声明一个变量接收传入的类型
// 类型推断:infer
// infer相当于声明一个变量接收传入的类型 自定义设置
type TypeFn1 = P extends { name: infer N; age: infer A } ? [N, A] : boolean;
let p: TypeFn1<{ name: string; age: number }> = ['', 0];
let p3: TypeFn1<{ height: string }> = false;
keyof 提取对象的属性名 、数组中的索引名、索引签名的类型
interface PersonItf {
name: string;
age: number;
height: string;
[index: number]: number;
}
type PersonType = keyof PersonItf; //把接口的属性名提取出来 'name' | 'age' | 'height' | number
let p: PersonType;
p = 'age';
p = 'name';
p = 'height';
p = 1;// 索引也可以提取 索引是number
interface FItf {
[key: string]: string;
}
let p1: FItf;
p1 = {
a: '1',
b: '2',
// c: 0, 会报错 value是string
};
// 提取对象的属性 对象的key值 可以是string 也可以是number
type FType = keyof FItf; // string | number
let p2: FType;
p2 = '';
p2 = '123';
p2 = 1;
type Required
我们只能在类型别名定义中使用 in,如果在接口(interface)中使用,则会提示一个错误
in 和 keyof 也只能在类型别名定义中组合使用
interface PersonItf1 {
// ['name']?: string; 在对象中可以这样获取 也可以obj.name
name: string;
// [name]?: string; 但是不可以[name获取] 因为name是变量
age?: number;
height: string;
}
type PersonType1 = Required;// 通过Requirred 可以看到映射类型
let str = ''; // string
type StrType = typeof str;
let s: StrType;
// s = 1; 报错 str是字符串属性
s = '1231223';
作者上班摸鱼被发现了,(入门学到这里基本是够的了)晚点再编写~~~