ts2类兼容性与类型别名

1.类兼容性
//  类兼容性:
//  1.只比较实例成员,不比较类的构造函数和静态成员
//  2.类的私有属性和保护属性会影响兼容性
class Person {
    public name:string =' dwa dw';
    // public age:number;
    public static age:number;
    public sex:string = 'ccc';
    constructor(name:string, age:number){}
}
class Animal {
    public name:string=' dwa dw';
    constructor(name:string){}
}
let p:Person;
let a:Animal;
p = a;  // 类型 "Animal" 中缺少属性 "sex",但类型 "Person" 中需要该属性。
a = p;  // 可多不可少



// 私有属性
class Person1 {
    protected name:string = 'xiaotian';
}

class Animal1 {
    protected name:string = 'xiaotian';
}

let proP1:Person1;
let A1:Animal1;
proP1 = A1; // 不能将类型“Animal1”分配给类型“Person1”。属性“name”受保护,但类型“Animal1”并不是从“Person1”派生的类
A1 = proP1; // 不能将类型“Person1”分配给类型“Animal1”。属性“name”受保护,但类型“Person1”并不是从“Animal1”派生的类
2.接口泛型兼容性
// 接口泛型兼容性
//  1.泛型只影响使用的部分,不会影响声明的部分
interface TestInterface<T>{
    // age:T //注释不会报错,但是不注释会报错Error
}

let t1:TestInterface<number>;
let t2:TestInterface<string>;
t1 = t2;
t2 = t1;
3.交叉类型与联合类型
// 交叉类型
// 格式:typ1 & type2 & ...
// 交叉类型是将多个类型合并为一个类型
let mergeFn = <T,U>(arg1:T,age2:U):(T & U) => {
    let res = {} as (T & U);
    res = Object.assign(arg1,age2);
    return res;
}

let res  = mergeFn({name:'xiaotian'},{age:22});
console.log(res); // { name: 'xiaotian', age: 22 }

// 联合类型
// 格式:type1 | type2 | ...
// 联合类型是多个类型中的任意一个类型
let va1:(number | boolean);
va1 = 2123;
va1 = true;
4.类型保护
// 类型保护
// 对于联合类型的变量,在使用时如何明确告诉编译器他是那种类型?
// 通过类型断言和类型保护
// 1.定义一个类型保护函数,这个函数的返回类型是一个布尔值
//   这个函数的返回类型是:传入的参数 + is具体类型
// 2.typeof来实现类型保护,只能用 === 或者 !==
//   使用使用typeof来实现类型保护,那么只能保护number/string/boolean/symbol类型
let getRandom = ():(string|number) => {
    let num = Math.random();
    return (num >= 0.5) ?'abc':1.667
}

let res = getRandom();
console.log(res);
// 通过类型断言可以明确告诉编译器当前是什么类型
// 但是每一次使用的时候都需要手动的告诉编译器,这样比较麻烦,冗余代码比较多
if((res as string).length){
    console.log((res as string).length);
}else{
    console.log((res as number).toFixed(2));
}

// 定义一个类型保护函数,这个函数的返回类型是一个布尔值
// 这个函数的返回类型是:传入的参数 + is具体类型
function isString(value:(number|string)):value is string{
    return typeof value === 'string';
}
if(isString(res)){
    console.log(res.length);
}else{
    console.log(res.toFixed(2));
}
// 除了可以通过定义类型保护函数的方法告诉编译器使用联合类型的变量具体是 什么类型以外,还可以使用typeof来实现类型保护
// 注意:typeof来实现类型保护,只能用 === 或者 !==
//      使用使用typeof来实现类型保护,那么只能保护number/string/boolean/symbol类型
if(typeof res ==='string'){
    console.log(res.length);
}else{
    console.log(res.toFixed(2));
}

// 除了typeof实现类型保护以外,还可以使用instanceof来实现类型保护
class Person {
    name:string = 'dwad';
}

class Student{
    age:number = 18;
}
let getRandomObject = ():(Person | Student) => {
    let num = Math.random();
    return num >= 0.5 ? new Person() : new Student();
}

let obj = getRandomObject();
console.log(obj,'obj'); // 可能是Person|Student 创建了实例对象
if(obj instanceof Person){
    console.log(obj.name);
}else{
    console.log(obj.age);
}
5.null和undefined
// null和undefined
// typescript有两种特殊的类型,null和undefined
// 1.默认情况下,可以将null和undefined赋值给任何类型
// 1.默认情况下,null和undefined也可以相互赋值
//      1.在开发中如果不想让null和undefined互相赋值,可以开启strictNullChecks = true
let val1:null;
let val2:undefined;
// val1 = val2;  // Error 不能将类型“undefined”分配给类型“null”。ts(2322)
// val2 = val1;  // Error 不能将类型“null”分配给类型“undefined”。ts(2322)
let value3:number;
// value3 = val1 // 不能将类型“null”分配给类型“number”。ts(2322)
// value3 = val2 // 不能将类型“undefined”分配给类型“number”。ts(2322)

// 如果开启了strictNullChecks,还想把undefined和null赋值给其他的类型那么使用联合类型
let value4:(number | null | undefined);
value4 = null;

// 对于可选属性和可选参数而言,如果开启了strictNullChecks,默认情况下,数据类型就是联合类型
// 就是当前的属性 + undefined类型
class Person {
    name?:string
}
function say(age?:number){
    console.log(age);
}
say(); // undefined
6.去除null和undefined
// 去除 null或者undefined检测
function getLength(values:(string|null|undefined)){
    // values = 'dwadwa'; // 我们明确知道这个类型是字符串
    return () => {
        // console.log(values.length); // Error 对象可能为 "null" 或“未定义”。ts(2533)
        // return (values || '').length;
        // return (values as string).length;
        return values!.length;

    }
}
getLength(null)();
7.类型别名
// 类型别名
//  1.类型别名就是给一个类型起一个别的名字,但是他们都表示同一个类型
//  2.类型别名可以使用泛型
//  3.可以在别的类型别名的属性中使用自己
//  4.接口和类型别名是相互兼容的

type MyString = string;
let value:MyString;
value = 'dwadw';
value = 21321; // 不能将类型“number”分配给类型“string”。ts(2322)
value = true;  // 不能将类型“boolean”分配给类型“string”。ts(2322)

// 类型别名可以使用泛型
type MyType<T> = {x:T,y:T};
let value1:MyType<number>;
value1 = {x:111,y:2123};
value1 = {x:'21232',y:1234}; // 不能将类型“string”分配给类型“number”。ts(2322)

// 可以在别的类型别名的属性中使用自己
type ChildType = {
    name:string;
    children?:ChildType
}
let childrenVa1:ChildType;
childrenVa1 = {
    name:'one',
    children:{
        name:'2121',
        children:{
            name:'dwawd'
        }
    }
}

// 接口和类型别名是相互兼容的
type TypeObj = {
    name:string
}

interface FaceObj {
    name:string
}
let typeV1:TypeObj = {name:'dwadw'};
let typeI1:FaceObj = {name:'dwadwdw'};
typeV1 = typeI1;
typeI1 = typeV1;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值