TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!

简介: 【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!

前言

Typescript是前端离不开的一项技术了,作为初学者,学习起来又很费劲!官网文档又臭又长,狗都不看!网上教程一上来就是20小时,让人望而生怯!

对于Typescript,我们其实并不需要学的非常深入,简单了解简单使用就好了!因此,一篇节省时间,通俗易懂的教程很重要!

本文就要简单但高效的带你入门ts!

基础类型简介

TypeScript 支持与 JavaScript 几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。TypeScript 包含的数据类型如下表:

数据类型 关键字 描述
任意类型 any 声明为 any 的变量可以赋予任意类型的值。
数字类型 number 双精度 64 位浮点值。它可以用来表示整数和分数。let binaryLiteral: number = 0b1010; // 二进制 let octalLiteral: number = 0o744; // 八进制 let decLiteral: number = 6; // 十进制 let hexLiteral: number = 0xf00d; // 十六进制
字符串类型 string 一个字符系列,使用单引号( ' )或双引号( " )来表示字符串类型。反引号( ` )来定义多行文本和内嵌表达式。let name: string = "Runoob"; let years: number = 5; let words: string = 您好,今年是 ${ name } 发布 ${ years + 1} 周年;
布尔类型 boolean 表示逻辑值:true 和 false。let flag: boolean = true;
数组类型 声明变量为数组。// 在元素类型后面加上[] let arr: number[] = [1, 2]; // 或者使用数组泛型 let arr: Array = [1, 2];
元组 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。let x: [string, number]; x = ['Runoob', 1]; // 运行正常 x = [1, 'Runoob']; // 报错 console.log(x[0]); // 输出 Runoob
枚举 enum 枚举类型用于定义数值集合。enum Color {Red, Green, Blue}; let c: Color = Color.Blue; console.log(c); // 输出 2
void void 用于标识方法返回值的类型,表示该方法没有返回值。function hello(): void { alert("Hello Runoob"); }
null null 表示对象值缺失。
undefined undefined 用于初始化变量为一个未定义的值
never never never 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。

注意: TypeScript 和 JavaScript 没有整数类型。

示例:src中创建学习文件夹

01_基础类型.ts

//基础类型
(()=>{
   
    //布尔类型  ------>boolean
    //数字类型 ------>number
    //字符串类型  ------->string
    .....................................
})()

main.ts中引入:

import './01_基础类型'
document.write ('哈哈哈哈。我要开始了')

布尔值

最基本的数据类型就是简单的 true/false 值,在JavaScript 和 TypeScript 里叫做 boolean(其它语言中也一样)。

//基础类型
(()=>{
   
    //布尔类型  ------>boolean
    //基本语法
    //let 变量名:数据类型 = 值
    let flag:boolean = true
    console.log(flag)
})()

数字

和 JavaScript 一样,TypeScript 里的所有数字都是浮点数。 这些浮点数的类型是 number。 除了支持十进制和十六进制字面量,TypeScript 还支持 ECMAScript 2015中引入的二进制和八进制字面量。

//基础类型
(()=>{
   
    //数字类型 ------>number
    let a1: number = 10 // 十进制
    let a2: number = 0b1010  // 二进制
    let a3: number = 0o12 // 八进制
    let a4: number = 0xa // 十六进制
    console.log(a1)
})()

字符串

JavaScript 程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样,我们使用 string 表示文本数据类型。 和 JavaScript 一样,可以使用双引号(")或单引号(')表示字符串。

//基础类型
(()=>{
   
    //字符串类型  ------->string
    let str1: string = '窗前明月光'

    //总结:ts中变量一开始是什么类型,那么后期赋值的时候,只能用这个类型
})()

undefined 和 null

TypeScript 里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null。 它们的本身的类型用处不是很大:

    let und:undefined = undefined
    let nul:null = null
    console.log(undefined)
    console.log(null)

默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number (其他)类型的变量。

但是,会出现报错,原因在于没有关闭tsc的严格模式。

在tsconfig.json中进行更改

  "strict": false,

然后npm run dev 重启服务就可以了。

数组

TypeScript 像 JavaScript 一样可以操作数组元素。

定义数组的两种方式

第一种,可以在元素类型后面接上[],表示由此类型元素组成的一个数组:

 let arr1:number[] = [1,2,3,4]
 console.log(arr1)

第二种方式是使用数组泛型,Array<元素类型>:

 let arr2:Array<number> = [5,6,7,8]
 console.log(arr2)

数组定义的方法汇总

定义联合类型数组

let arr:(number | string)[];
// 这个数组中将来既可以存储数值类型的数据, 也可以存储字符串类型的数据
arr3 = [1, 'b', 2, 'c'];

定义指定对象成员的数组:

interface Arrobj{
   
    name:string,
    age:number
}
let arr3:Arrobj[]=[{
   name:'jimmy',age:22}]

元组 Tuple

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string 和 number 类型的元组。

    let arr3 :[string,number,boolean] = ["1",2,true]
    console.log(arr3)

元组类型的可选元素

与函数签名类型,在定义元组类型时,我们也可以通过 ? 号来声明元组类型的可选元素

let optionalTuple: [string, boolean?] = ["Semlinker", true];
let optionalTuple: [string, boolean?] = ["Semlinker"];

元组类型的剩余元素

元组类型里最后一个元素可以是剩余元素,形式为 ...X,这里 X 是数组类型。剩余元素代表元组类型是开放的,可以有零个或多个额外的元素。 例如,[number, ...string[]] 表示带有一个 number 元素和任意数量string 类型元素的元组类型。为了能更好的理解,我们来举个具体的例子:

type RestTupleType = [number, ...string[]];
let restTuple: RestTupleType = [666, "Semlinker", "Kakuqo", "Lolo"];

只读的元组类型

任何元组类型加上 readonly 关键字前缀,以使其成为只读元组。具体的示例如下:

const point: readonly [number, number] = [10, 20];

在使用 readonly 关键字修饰元组类型之后,任何企图修改元组中元素的操作都会抛出异常

枚举

enum 类型是对 JavaScript 标准数据类型的一个补充。 使用枚举类型可以为一组数值赋予友好的名字。

enum Color {
   
  Red,
  Green,
  Blue
}

// 枚举数值默认从0开始依次递增
// 根据特定的名称得到对应的枚举数值
let myColor: Color = Color.Green  // 0
console.log(myColor, Color.Red, Color.Blue)

默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1 开始编号:

enum Color {
   Red = 1, Green, Blue}
let c: Color = Color.Green

或者,全部都采用手动赋值:

enum Color {
   Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green

枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为 2,但是不确定它映射到 Color 里的哪个名字,我们可以查找相应的名字:

enum Color {
   Red = 1, Green, Blue}
let colorName: string = Color[2]

console.log(colorName)  // 'Green'

any

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:

let notSure: any = 4 
notSure = 'maybe a string' 
notSure = false // 也可以是个 boolean

在对现有代码进行改写的时候,any 类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。并且当你只知道一部分数据的类型时,any 类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据:

let list: any[] = [1, true, 'free'] list[1] = 100

void

某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void:

/* 表示没有任何类型, 一般用来说明函数的返回值不能是undefined和null之外的值 */ 
function fn(): void {
     
  console.log('fn()')   
  // return undefined  
  // return null 
  // return 1 // error 
}

声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null:

let unusable: void = undefined

联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种
需求1: 定义一个一个函数得到一个数字或字符串值的字符串形式值

function toString2(x: number | string) : string {
   
  return x.toString()
}

需求2: 定义一个一个函数得到一个数字或字符串值的长度

function getLength(x: number | string) {

  // return x.length // error

  if (x.length) { // error
    return x.length
  } else {
    return x.toString().length
  }
}

类型断言

通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。

类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法

/* 
类型断言(Type Assertion): 可以用来手动指定一个值的类型
语法:
    方式一: <类型>值
    方式二: 值 as 类型  tsx中只能用这种方式
*/

/* 需求: 定义一个函数得到一个字符串或者数值数据的长度 */
function getLength(x: number | string) {
   
  if ((<string>x).length) {
   
    return (x as string).length
  } else {
   
    return x.toString().length
  }
}
console.log(getLength('abcd'), getLength(1234))

类型推断

类型推断: TS会在没有明确的指定类型的时候推测出一个类型
有下面2种情况: 1. 定义变量时赋值了, 推断为对应的类型. 2. 定义变量时没有赋值, 推断为any类型

/* 定义变量时赋值了, 推断为对应的类型 */
let b9 = 123 // number
// b9 = 'abc' // error

/* 定义变量时没有赋值, 推断为any类型 */
let b10  // any类型
b10 = 123
b10 = 'abc'

代码融合

//基础类型
(()=>{
   
    //布尔类型  ------>boolean
    //基本语法
    //let 变量名:数据类型 = 值
    let flag:boolean = true
    console.log(flag)

    //数字类型 ------>number
    let a1: number = 10 // 十进制
    let a2: number = 0b1010  // 二进制
    let a3: number = 0o12 // 八进制
    let a4: number = 0xa // 十六进制
    console.log(a1)

    //字符串类型  ------->string
    let str1: string = '窗前明月光'

    //总结:ts中变量一开始是什么类型,那么后期赋值的时候,只能用这个类型

    let und:undefined = undefined
    let nul:null = null
    console.log(undefined)
    console.log(null)
    //undefined和null都可以作为其他类型的子类型,把/undefined和null赋值给其他类型的变量,如:number类型的变量
    let num2:number = undefined


    console.log('数组类型'+'=====================================')
    //数组类型
    //数组定义方式一
    //语法;let变量名 :数据类型[] = [值1,值2,值3]
    let arr1:number[] = [1,2,3,4]
    console.log(arr1)
    //数组定义方法二:泛型的写法
    //语法:let 变量名:Array<数据类型> = [值1,值2,值3]
    let arr2:Array<number> = [5,6,7,8]
    console.log(arr2)


    //注意问题:数组定以后,里面的数据类型必须和定义的时候类型保持一致,否则会报错。

    console.log('元组类型'+'=====================================')
    //元祖类型
    //在定义数组时,类型和数据的个数一开始就已经知道了
    let arr3 :[string,number,boolean] = ["1",2,true]
    console.log(arr3)


    //注意问题:元组类型使用时,数据的类型的位置和数据的个数应该和定义在元组的时候的数据类型及位置应该是一致的。


    console.log('枚举类型'+'=====================================')
    //enum 类型是对 JavaScript 标准数据类型的一个补充。 使用枚举类型可以为一组数值赋予友好的名字。
    enum Color {
   
        Red,
        Green,
        Blue
    }

    // 枚举数值默认从0开始依次递增
    // 根据特定的名称得到对应的枚举数值
    let myColor: Color = Color.Green 
    console.log(myColor)   // 1

    //默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1 开始编号:
    enum Color2 {
   Red = 10, Green, Blue}
    let c: Color2 = Color2.Green  
    console.log(c)   // 11

    //或者,全部都采用手动赋值:
    enum Color3 {
   Red = 11111, Green = 22222, Blue = 4444}
    let c2: Color3 = Color3.Green
    console.log(c2)

    //枚举类型提供的一个便利是你可以由枚举的值得到它的名字。
    // 例如,我们知道数值为 2,但是不确定它映射到 Color 里的哪个名字,我们可以查找相应的名字:
    enum Color4 {
   Red = 1, Green, Blue}
    let colorName: string = Color4[2]

    console.log(colorName)  // 'Green'


    console.log('any类型'+'=====================================')
    //let str :any =100
    let notSure: any = 4 
    notSure = 'maybe a string' 
    notSure = false // 也可以是个 boolean 

    console.log('对象类型'+'=====================================')
    //object类型
    //定义一个函数,参数是对象类型,返回值也是对象类型
    function getName(name:Object):Object{
   
        console.log(name)
        return{
   
            name:name,
            age:24
        }
    }
    getName({
   name:'佐助'})

    console.log('联合类型及类型断言'+'=====================================')
    //联合类型(Union Types)表示取值可以是多种类型中的一种
    //需求1:定义一个函数得到一个数字或字符串值得字符串形式值
    function getString(str:string | number):string{
   
        return str.toString()
    }
    console.log(getString(123))

    //类型断言:告诉编译器,我知道自己是什么类型,也知道自己在干什么
    //语法一:<类型>变量名
    //语法二:值 as 类型
    //需求2:定义一个函数得到一个数字或字符串值得长度
    function getStringL(str:string | number):number{
   
        // return str.toString().length
        //如果str本身就是string类型,那么没必要调用tostring方法的
        if((<string>str).length){
   
            // return (<string>str).length
            return (str as string).length
        }else{
   
            return str.toString().length
        }

    }
    console.log(getStringL(123445555555))

    console.log('类型推断'+'=====================================')
    let txt = 100


})()

never

never类型表示的是那些永不存在的值的类型。

值会永不存在的两种情况:

  1. 如果一个函数执行时抛出了异常,那么这个函数永远不存在返回值(因为抛出异常会直接中断程序运行,这使得程序运行不到返回值那一步,即具有不可达的终点,也就永不存在返回了);
  2. 函数中执行无限循环的代码(死循环),使得程序永远无法运行到函数返回值那一步,永不存在返回。
// 异常
function err(msg: string): never {
    // OK
  throw new Error(msg); 
}

// 死循环
function loopForever(): never {
    // OK
  while (true) {
   };
}

never类型同null和undefined一样,也是任何类型的子类型,也可以赋值给任何类型。

但是没有类型是never的子类型或可以赋值给never类型(除了never本身之外),即使any也不可以赋值给never

let ne: never;
let nev: never;
let an: any;

ne = 123; // Error
ne = nev; // OK
ne = an; // Error
ne = (() => {
    throw new Error("异常"); })(); // OK
ne = (() => {
    while(true) {
   } })(); // OK

在 TypeScript 中,可以利用 never 类型的特性来实现全面性检查,具体示例如下:

type Foo = string | number;

function controlFlowAnalysisWithNever(foo: Foo) {
   
  if (typeof foo === "string") {
   
    // 这里 foo 被收窄为 string 类型
  } else if (typeof foo === "number") {
   
    // 这里 foo 被收窄为 number 类型
  } else {
   
    // foo 在这里是 never
    const check: never = foo;
  }
}

注意在 else 分支里面,我们把收窄为 never 的 foo 赋值给一个显示声明的 never 变量。如果一切逻辑正确,那么这里应该能够编译通过。但是假如后来有一天你的同事修改了 Foo 的类型:

type Foo = string | number | boolean;

然而他忘记同时修改 controlFlowAnalysisWithNever 方法中的控制流程,这时候 else 分支的 foo 类型会被收窄为 boolean 类型,导致无法赋值给 never 类型,这时就会产生一个编译错误。通过这个方式,我们可以确保controlFlowAnalysisWithNever 方法总是穷尽了 Foo 的所有可能类型。 通过这个示例,我们可以得出一个结论:使用 never 避免出现新增了联合类型没有对应的实现,目的就是写出类型绝对安全的代码。

关联文章

TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!

相关文章
|
4天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
6天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1551 7
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
9天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
639 25
|
6天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
209 3
|
1天前
|
Java 开发者
【编程进阶知识】《Java 文件复制魔法:FileReader/FileWriter 的奇妙之旅》
本文深入探讨了如何使用 Java 中的 FileReader 和 FileWriter 进行文件复制操作,包括按字符和字符数组复制。通过详细讲解、代码示例和流程图,帮助读者掌握这一重要技能,提升 Java 编程能力。适合初学者和进阶开发者阅读。
100 60
|
13天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
615 5
|
12天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
2天前
vue3+Ts 二次封装ElementUI form表单
【10月更文挑战第8天】
107 56
|
25天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。