精华内容
下载资源
问答
  • TS类型断言简化对象类型声明

    千次阅读 2020-10-09 20:22:05
    TS类型断言简化对象类型声明 前言 在使用了 typescript 的项目开发中,有时候为了某个对象进行声明,经常需要写完 interface 之后,在赋值的时候又写了一遍一模一样的代码;当想对它增加一个键值,又得去增加 ...

    前言

    在使用了 typescript 的项目开发中,有时候为了某个对象进行声明,经常需要写完 interface 之后,在赋值的时候又写了一遍相似的代码;当想对它增加一个键值,又得去增加 interface 的字段声明。因此很想和声明一个变量那样,在写键值的时候直接进行类型声明。

    对象的传统声明方式

    对于对象的类型声明,我们经常使用 interface、type、class 的方式,先对整体类型进行声明,然后再去赋值,例如:

    interface IInterface {
      id: number;
      name: string;
    }
    
    type IType = {
      id: number,
      name: string,
    }
    
    class IClass {
      id: number;
      name: string;
    }
    
    const data: IType = {
      id: 1,
      name: 'A'
    }
    

    但是这样会出现代码重复,特别是当键值对很多或者不确定数量的时候,经常需要去维护类型声明和赋值两部分“长得很像”的代码。

    使用类型断言声明

    有时候我们只是希望在后续的赋值操作中不会出现类型错误,或者只是一次性的声明不打算复用。那么可以采用下面的方式实现:

    const data = {
      id: 1 as number,
      name: 'A' as string,
    }
    
    data.id = '123';   // 不允许
    data.name = 'B';   // 允许
    

    实际上,这里使用到了TypeScript 的类型断言,这里的 as 是 Assertion 的意思,将对 as 后面的类型(或者字面量表示的类型)进行推断。

    它的原理大概是这样的:

    1. data 没有声明类型,所以被当做 any
    2. 给 data 赋值了一个对象,每个字段的键值类型也都是 any
    3. 使用类型断言,例如 id: 1 as number,将 any 覆盖为 number.

    存在的类型安全问题

    使用类型断言无法表达 readonly 以及赋值范围,将会导致类型安全问题。参考下面例子:

    interface IType {
      readonly id: number;
      sex: 0 | 1;
    }
    const data: IType = {
      id: 1,
      sex: 1
    };
    data.id = 2;  // 不允许
    data.sex = 2; // 不允许
    
    const data = {
      id: 1 as number,  // 没有正确语法位置可以写 readonly
                        // 例如 id: 1 as readonly number 是错误语法
      sex: 1 as 0 | 1   // 写了 0 | 1,实际上会被推断为 number
    };
    data.id = 2;  // 允许⚠️
    data.sex = 2; // 允许⚠️
    

    虽然只用类型断言无法表达 readonly 和赋值范围,但我们可以曲线救国,糅合两种类型声明方式,但显得很杂。

    以 vue data 为例

    下面以 vue 的 data 为例,可以直观对比出代码量的缩减:

    // 使用传统声明方式
    interface IData {
      id: number;
      name: string;
      age: number;
      addr: string;
      phone: string;
      sex: 0 | 1;
      height: number | string;
      weight: number | string;
      birthday: Date;
    }
    export default {
      data(): IData {
        return {
          id: 1,
          name: '',
          age: 25,
          addr: '',
          phone: '',
          sex: 0,
          height: 180,
          weight: '75kg',
          birthday: new Date('1995-01-01')
        }
      }
    }
    
    // 使用类型断言
    interface IDataMin {
      readonly id: number;
      sex: 0 | 1;
    }
    export default {
      data(): IDataMin {
        return {
          id: 1,	// 已在上面声明
          name: '' as string,
          age: 25 as number,
          addr: '' as string,
          phone: '' as string,
          sex: 0,	// 已在上面声明
          height: 180 as number | string,
          weight: '75kg' as number | string,
          birthday: new Date('1995-01-01') as Date
        }
      }
    }
    

    不适用的情况

    • 需要设置较多 readonly、赋值范围的时候
    • 类型声明需要被复用的时候
    • 项目风格要求类型与赋值解耦的时候
    展开全文
  • ts入门笔记——ts类型声明和类型断言 学习路径 1.学习ts声明变量类型 2.学习ts的类型断言(解释型类型转换) 3.学习ts的接口进一步详解 ts在线运行练习网站:https://www.tslang.cn/play/index.html 一、ts简介 1....

    最近玩csdn比较少,欢迎关注我的掘金:杨灿就是杨火山

    简单快速上手ts的学习路径:

    一、熟悉掌握熟悉的强类型定义,初步学习编写强类型代码。

    1. 学习ts的声明变量类型,能够初步编写强类型代码;
    2. 学习ts的接口,进一步强定义对象的丰富属性;
    3. 学习ts的函数声明和实现定义,强类型化你的js函数;

    二、灵活面对类型转换,类型报错,类型文件的声明和引入,灵活编写强类型代码。

    1. 学习ts的类型断言(解释型类型转换);
    2. 学习ts的泛型,更灵活的面对多可能性类型参数;
    3. 学习ts的类型声明文件,全局定义;

    ts在线运行练习网站:https://www.tslang.cn/play/index.html

    一、ts简介

    1.什么是TypeScript(TS)?

    TypeScript简称TS
    TS和JS之间的关系其实就是Less/Sass和CSS之间的关系
    就像Less/Sass是对CSS进行扩展一样, TS也是对JS进行扩展
    就像Less/Sass最终会转换成CSS一样, 我们编写好的TS代码最终也会换成JS

    2.为什么需要TypeScript?

    因为JavaScript是弱类型, 很多错误只有在运行时才会被发现
    而TypeScript是强类型, 它提供了一套静态检测机制,如何我们编码事中途变换变量的类型,ts就会在报错,帮助我们在编码时发现错误。

    Ts为帮助js弥补在大型项目中的缺陷而生。

    3.TypeScript特点

    • 支持最新的JavaScript新特特性
    • 支持代码静态检查
    • 支持诸如C,C++,Java,Go等后端语言中的特性
      (枚举、泛型、类型转换、命名空间、声明文件、类、接口等)

    二、ts中的类型声明

    TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型、元祖方便我们使用

    1.boolean、number、string简单类型的变量声明

    布尔类型 boolean

    let val2:boolean;
    val2 = true;
    // val2 = 1; // 会报错
    console.log(val2);
    

    数值类型 number

    let val1:number; // 定义了一个名称叫做val1的变量, 这个变量中将来只能存储数值类型的数据
    val1 = 123;
    // val1 = "123"; // 会报错
    // 注意点: 其它的用法和JS一样
    // val1 = 0x11;
    // val1 = 0o11;
    // val1 = 0b11;
    console.log(val1);
    

    字符串类型 string

    let val3:string;
    val3 = "123";
    val3 = `val1=${val1}, val2==${val2}`;
    console.log(val3);
    

    2.数组和元祖类型的变量声明

    (1)整个数组数据类型一致的情况

    方式一: Array < number >
    // 需求: 要求定义一个数组, 这个数组中将来只能存储数值类型的数据
    let arr1:Array<number>; // 表示定义了一个名称叫做arr1的数组, 这个数组中将来只能够存储数值类型的数据
    arr1 = [1, 3, 5];
    // arr1 = ['a', 3, 5]; // 报错
    console.log(arr1);
    
    方式二: string[ ] (建议)
    // 需求: 要求定义一个数组, 这个数组中将来只能存储字符串类型的数据
    let arr2:string[]; // 表示定义了一个名称叫做arr2的数组, 这个数组中将来只能够存储字符串类型的数据
    arr2 = ['a', 'b', 'c'];
    // arr2 = [1, 'b', 'c']; // 报错
    console.log(arr2);
    

    (2)整个数组数据类型不一致的情况

    联合类型声明数组 (number | string)[ ]
    let arr3:(number | string)[];
    // 表示定义了一个名称叫做arr3的数组, 这个数组中将来既可以存储数值类型的数据, 也可以存储字符串类型的数据
    arr3 = [1, 'b', 2, 'c'];
    // arr3 = [1, 'b', 2, 'c', false]; // 报错
    console.log(arr3);
    

    (3) 自由任意类型元素的数组

    any[ ]
    let arr4:any[]; // 表示定义了一个名称叫做arr4的数组, 这个数组中将来可以存储任意类型的数据
    arr4 = [1, 'b', false];
    console.log(arr4);
    

    (4) 严格限制类型和长度的元祖数组

    元祖类型 [string, number, boolean]

    TS中的元祖类型其实就是数组类型的扩展,元祖用于保存定长定数据类型的数据

    let arr5:[string, number, boolean]; 
    
    // 表示定义了一个名称叫做arr5的元祖, 这个元祖中将来可以存储3个元素, 第一个元素必须是字符串类型, 第二个元素必须是数字类型, 第三个元素必须是布尔类型
    
    arr5 = ['a', 1, true];
    // arr5 = ['a', 1, true, false]; // 超过指定的长度会报错
    arr5 = ['a', 1, true];
    console.log(arr5);
    

    3.enum枚举类型

    枚举用于表示固定的几个取值,例如: 一年只有四季、人的性别只能是男或者女。
    枚举类型是TS为JS扩展的一种类型, 在原生的JS中是没有枚举类型的。

    定义:

    
    enum Gender{
        Male=0,
        Femal=1
    }
    
    // 简写
    enum Gender{
        Male,
        Femal
    }
    
    // 定义了一个名称叫做Gender的枚举类型, 这个枚举类型的取值有两个, 分别是Male和Femal
    

    使用:

    let val:Gender; 
    // 定义了一个名称叫做val的变量, 这个变量中只能保存Male或者Femal
    val = Gender.Male;
    val = Gender.Femal;
    // val = 'nan'; // 报错
    // val  = false;// 报错
    
    
    // 注意点: TS中的枚举底层实现的本质其实就是数值类型, 所以赋值一个数值不会报错
    // val = 666; // 不会报错
    // console.log(Gender.Male); // 0
    // console.log(Gender.Femal);// 1
    
    
    // 注意点: TS中的枚举类型的取值, 默认是从上至下从0开始递增的
    //         虽然默认是从0开始递增的, 但是我们也可以手动的指定枚举的取值的值
    // 注意点: 如果手动指定了前面枚举值的取值, 那么后面枚举值的取值会根据前面的值来递增
    // console.log(Gender.Male); // 6
    // console.log(Gender.Femal);// 7
    
    // 注意点: 如果手动指定了后面枚举值的取值, 那么前面枚举值的取值不会受到影响
    // console.log(Gender.Male); // 0
    // console.log(Gender.Femal);// 6
    
    // 注意点: 我们还可以同时修改多个枚举值的取值, 如果同时修改了多个, 那么修改的是什么最后就是什么
    // console.log(Gender.Male); // 8
    // console.log(Gender.Femal);// 6
    
    
    // 我们可以通过枚举值拿到它对应的数据
    console.log(Gender.Male); // 0
    // 我们还可以通过它对应的数据拿到它的枚举值
    console.log(Gender[0]); // Male
    

    探究底层实现原理

    var Gender;
    (function (Gender) {
     // Gender[key] = value;
        Gender[Gender["Male"] = 0] = "Male";
        Gender[Gender["Femal"] = 1] = "Femal";
    })(Gender || (Gender = {}));
    
    // Gender[Gender["Male"] = 0] = "Male" 相当于 Gender["Male"] = 0;Gender[0] = "Male";
    
    let Gender = {};
    Gender["Male"] = 0;
    Gender[0] = "Male";
    Gender["Femal"] = 1;
    Gender[1] = "Femal";
    

    4.any 任意类型

    any表示任意类型, 当我们不清楚某个值的具体类型的时候我们就可以使用any,任何数据类型的值都可以赋值给any类型

    一般用于定义一些通用性比较强的变量, 或者用于保存从其它框架中获取的不确定类型的值

    注意不要过多使用any,因为什么都是any那ts就变成js了

    let value:any; // 定义了一个可以保存任意类型数据的变量
    value = 123;
    value = "abc";
    value = true;
    value = [1, 3, 5];
    

    5.void类型

    void与any正好相反, 表示没有任何类型, 一般用于函数返回值。在TS中只有null和undefined可以赋值给void类型

    function test():void {
        console.log("hello world");
    }
    test();
    
    let value:void; // 定义了一个不可以保存任意类型数据的变量, 只能保存null和undefined
    // value = 123; // 报错
    // value = "abc";// 报错
    // value = true;// 报错
    // 注意点: null和undefined是所有类型的子类型, 所以我们可以将null和undefined赋值给任意类型
    // value = null; // 不会报错
    value = undefined;// 不会报错
    

    6.never类型

    表示的是那些永不存在的值的类型,一般用于抛出异常或根本不可能有返回值的函数。

    // function demo():never {
    //     throw new Error('报错了');
    // }
    // demo();
    
    // function demo2():never {
    //     while (true){}
    // }
    // demo2();
    

    7.Object对象类型

    let obj:object; // 定义了一个只能保存对象的变量
    // obj = 1;
    // obj = "123";
    // obj = true;
    obj = {name:'lnj', age:33};
    console.log(obj);
    

    如何表示一个具体的对象数据结构呢?
    答案:可以使用ts的接口,在后续文章中会详细介绍。

    8. 接口interface类型

    (1)什么是接口类型?

    和number,string,boolean,enum这些数据类型一样,接口也是一种类型, 也是用来约束使用者的。

    (2)定义和使用

    // 需求: 要求定义一个函数输出一个人完整的姓名, 这个人的姓必须是字符串, 这个人的名也必须是一个字符
    
    interface FullName{
        firstName:string
        lastName:string
    }
    
    let obj = {
        firstName:'Jonathan',
        lastName:'Lee'
        // lastName:18 会报错
    };
    
    //{firstName, lastName}使用了解构赋值
    function say({firstName, lastName}:FullName):void {
        console.log(`我的姓名是:${firstName}_${lastName}`);
    }
    say(obj);
    
    

    ts入门笔记目录:

    TS入门笔记1——TS的类型声明

    TS入门笔记2——TS接口进阶详解

    TS入门笔记3——TS中的函数声明

    TS入门笔记4——TS的类型断言(解释型类型转换)

    TS入门笔记5——TS的泛型

    TS入门笔记6——ts中的声明文件、模块、命名空间

    记录知识,传递快乐~

    如果我的总结对你有帮助,请给我点个赞,你的鼓励是我持续记录的一大动力~

    如果文章中有错误,请多包涵,欢迎在评论中指出~

    展开全文
  • TS入门笔记4——TS类型断言(解释型类型转换)1.什么是类型断言?个人理解类型断言主要分为两种含义: (1)解释型强制类型转换(个人理解)(2)类型断言就是告诉编译器, 你不要帮我们检查了, 相信我,它就是这个...

    TS入门笔记4——TS的类型断言(解释型类型转换)

    1.什么是类型断言?

    个人理解类型断言主要分为两种含义:

    (1)解释型强制类型转换(个人理解)

    (2)类型断言就是告诉编译器, 你不要帮我们检查了, 相信我,它就是这个类型。

    2.使用

    方式一

    let len = (<string>str).length;
    
    //有兼容性问题, 在使用到了JSX的时候兼容性不是很好

    方式二 as (建议)

    let len = (str as string).length;

    3.示例

    例如: 我们拿到了一个any类型的变量, 但是我们明确的知道这个变量中保存的是字符串类型,此时我们就可以通过类型断言将any类型转换成string类型, 使用字符串类型中相关的方法了。

    let str:any = 'it666';
    // 当还是any的时候是没有.length的提示的
    let len = (str as string).length;
    console.log(len);


    ts入门笔记目录:

    TS入门笔记1——TS的类型声明

    TS入门笔记2——TS接口进阶详解

    TS入门笔记3——TS中的函数声明

    TS入门笔记4——TS的类型断言(解释型类型转换)

    TS入门笔记5——TS的泛型

    TS入门笔记6——ts中的声明文件、模块、命名空间

    a90b36dbca8b2df568e1ac29bbe4aa12.png
    记录知识,传递快乐~
    如果我的总结对你有帮助,请给我点个赞,你的鼓励是我持续记录的一大动力~
    如果文章中有错误,请多包涵,欢迎在评论中指出~
    展开全文
  • ts断言

    2021-04-08 15:54:39
    用于属性的读取,都可以缩小类型检查范围,都做判空用途时是等价的。只是!具体用于告知编译器此值不可能为空值(null和undefined),而as不限于此。 2、?可用于属性的定义和读取,读取时告诉编译器此值可能为空值...

    今天看vue的源码。看到了变量后加!的用法;后来查了一下:

    结论

    1、as和!用于属性的读取,都可以缩小类型检查范围,都做判空用途时是等价的。只是!具体用于告知编译器此值不可能为空值(null和undefined),而as不限于此。

    2、?可用于属性的定义和读取,读取时告诉编译器此值可能为空值(null和undefined),需要做判断。

     

    as:

    let someValue: any = "this is a string";

    let strLength: number = (someValue).length;

     

    let someValue: any = "this is a string";

    let strLength: number = (someValue as string).length;

    let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;

     

    问号(?)用于属性定义

    问号表示可选的属性,一般用于属性定义,如,用于接口时:

    interface SquareConfig {
        color?: string;
        width?: number;
    }

    SquareConfig的定义与下面的代码等价:

    interface SquareConfig {
        color: string|undefined;
        width: number|undefined;
    }

     

    展开全文
  • 类型断言 && 变量声明 基础类型 原始类型 let isDone: boolean = false; let decLiteral: number = 6; let name: string = "bob"; let list: number[] = [1, 2, 3]; let list: Array<number> = [1, ...
  • 它是JavaScript的一个超集,而且本质上TypeScript扩展了JavaScript的语法解决JavaScript的“痛点”:弱类型和没有命名空间,导致很难模块化 为什么要用TypeScript 1、开源 2、简单 TypeScript 是 JavaScript 的超集...

空空如也

空空如也

1 2 3 4 5 6
收藏数 112
精华内容 44
关键字:

ts类型断言