如何学习TS?

在这里插入图片描述

文章目录

    • 一. 8种内置基础类型.ts
    • 二. void、never、any、unknown类型
        • void类型
        • never类型
        • any类型
        • unknown类型
        • 总结:
            • void和any在项目中是比较常见的,never和unknown不常用。
    • 三. 数组和函数类型定义.ts
    • 四. 元组与交叉类型使用
    • 元组
            • 数组一般有同类型的值组成,但有时候存在多种类型,我们多种类型定义称为元组。
            • 数组定义:同一类型
            • 元组定义:不同类型
    • 交叉类型
            • 把多个类型合并为一个类型,称为交叉类型。
            • 联合类型表示或的关系
            • 交叉类型表示取两个类型的并集
            • 例子:
            • 例子:
    • 五. 接口五种场景与使用
            • 接口定义:
            • 属性只读或可选
            • 任意属性
            • 定义函数类型
            • 接口继承
            • 接口和Type区别?
            • 例子:
    • 六. 泛型三种定义与使用方式
    • 七. 关键知识点 keyof,typeof, in的使用
            • keyof
            • typeof
            • in
            • 例子:
    • 八.tsconfig.json配置
            • 基础字段
            • 编译配置
    • 总结

一. 8种内置基础类型.ts

/* eslint-disable @typescript-eslint/no-unused-vars */
// 定义类型: string
const name: string = 'jack'// 定义类型: number
const age: number = 30// 定义类型: boolean
const isTrue: boolean = true// 特殊的几个:---------
// 定义undefined类型
let a: undefined// 定义null类型
const b: null = null// 定义object类型
const user: object = {}// 或者
const user1: { name: string; age: number } = { name: 'zhangsan', age: 24 }// 定义bigint类型
const big: bigint = 100n// 定义symbol符号类型
const sym: symbol = Symbol('hepan')export default {}

二. void、never、any、unknown类型

void类型

void表示没有任何类型,不能直接赋值。

let a: void; 
let b: number = a; // 报错

给变量赋值为void是没有意义的。

如果一个函数没有返回值,此时我们可以定义为void

function fn():void {console.log('今天天气不错')
}<a href="javascript:void;"></a>
never类型

never类型表示永不存在的值的类型。
(在报错或者死循环时候使用)

// 抛出异常
function error(): never {throw new Error('我是一个Error'); 
}// 死循环
function loop(): never {while (true) {console.log('这里是死循环')};
}
any类型

any类型表示任意类型。

let num:number = 1000;
num = "jack" // 报错let num:any = 1000;
num = "jack" // 不报错// 调用方法,依然不报错
num.setName('jack')

虽然any不做任何约束,但是非常不推荐这样使用,这样会带来隐患。

我们在开发组件、模块、定义函数、调用接口时,如果类型很难定义出来、不知道属于什么类型等场景,可以适当使用any类型。

unknown类型

unknownany一样,所有类型都可以分配给unknown,反之把unknown 赋值给其它类型会报错。

// unknown 可以接收任意类型
let name:string = "jack"
let user:unknown = name;// unknown 不可以赋值给其它类型,any除外,下面会报错
let name:unknown = "jack"
let user:string = name;

(在报错或者死循环时候使用)

// 抛出异常
function error(): unknown {throw new Error('我是一个Error'); 
}// 死循环
function loop(): unknown {while (true) {console.log('这里是死循环')};
}
总结:
  • 能确定类型的,尽量定义类型。

  • 无法确定类型的,可以使用 any 进行兜底。

  • 当函数没有返回值时,可以使用void定义。

  • any和unknown可以接收任意类型值,any可以赋值给任意类型,但unknown不可以赋值给任意类型。

  • void和any在项目中是比较常见的,never和unknown不常用。

三. 数组和函数类型定义.ts

// 数组类型的定义
const list1: number[] = [1, 2, 3]const list2: Array<number> = [1, 2, 3]const list3: [number, string, boolean] = [1, '2', true]const list4: [{ name: string; age: number }] = [{ name: 'jack', age: 30 }]const list5: Array<{ name: string; age: number }> = [{ name: 'jack', age: 30 }]interface User {name: stringage: number
}const list6: Array<User> = [{ name: 'jack', age: 30 }]// 函数类型的定义
// :在函数括号后加冒号
// 变量类型定义:在变量后加冒号function add1(a: number, b: number): number {return a + b
}function add2(a: number, b: number): void {console.log(a + b)
}// 定义报错用unkown
function add3(a: number, b: number): unknown {throw new Error('Error')
}// 箭头函数两种定义
// (括号后面加冒号)
const add4 = (a: number, b: number): number => {return a + b
}// (变量后加冒号)
const add5:(a: number, b: number) => number = (a: number, b: number) => {return a + b
}export default {}

四. 元组与交叉类型使用

元组

数组一般有同类型的值组成,但有时候存在多种类型,我们多种类型定义称为元组。
数组定义:同一类型
// 纯数字
let list:number[] = [1,2,3]
// 纯字符串
let list:string[] = ['1','2','3']// 使用Array泛型
let list:Array<number> = [1,2,3]
元组定义:不同类型
const list: [number, string, boolean] = [1, '2', true]// 解构
const user:[number,string] = [1,'Jack']
const [id,name] = user;// 可选类型
const list:[number,number,number?] = [1,2,3]
const list:[number,number,number?] = [1,2]

交叉类型

多用对象定义
https://zhuanlan.zhihu.com/p/627526459

把多个类型合并为一个类型,称为交叉类型。
联合类型表示或的关系

a|b,
a, b, a b

交叉类型表示取两个类型的并集

取出范围最大的

例子:
// JS里面使用且
const count = 10;
if(count > 0 && count <10) console.log('执行代码')
// TS里面也是类似写法,我们先看或使用// 1. 或使用let id = 1; 
let id = '1';// 联合类型
let id:number | string = 1; 

那且如何使用?一个变量不可能即是数字又是字符串

// 错误的用法
let id: number & string = 1; type UserType = { id: number, name: string}
type AgeType = { age: number}const user:UserType & AgeType = { id:1, name: 'jack', age: 30}
例子:
// 元组&交叉类型.ts// 元组
const list: [number, string, boolean, object] = [1, '2', true, {}]// 交叉类型
type AgeType = { age: number }
type UserType = { id: number; name: string }const user: UserType & AgeType = { id: 1, name: 'jack', age: 30 }
const userAge:AgeType = {age: 30}const userInfo: UserType = {id: 2, name: 'Tom'}export default {}

五. 接口五种场景与使用

在Java语言中,接口是一个非常重要的概念,是对行为的抽象,具体功能由类去负责实现。

在TypeScript中,接口是一个非常灵活的概念,除了用于抽象以外,还可以用于类型的描述。

接口定义:
interface Person {name: string;age: number;
}const jack:Person = {name: 'Jack',age:30
}// 少字段会报错
const tom:Person = {name: 'Tom',
}// 多字段也会报错
const tom:Person = {name: 'Tom',age: 30,money: 100
}

接口一般首字母大写

属性只读或可选
interface Person {readonly name: string;age?: number;
}// 正确
const tom:Person = {name: 'tom'
}// 报错
tom.name = 'jack'
任意属性

比如说,我们不确定这个用户具体有哪些属性,怎么去定义类型?

interface Person {name: string;age: number;
} const tom:Person = {id: 1,name: 'tom',age: 30,gender: 'male',edu: '本科'
}// 添加任意属性
interface Person {name: string;age: number;[k:string] : any; 
} 

注意:一旦定义了任意属性,那么确定的属性和类型必须是它的类型的子集。

定义函数类型
const add = (x, y) => {return x + y
}// 添加类型
const add = (x:number, y:number):number => {return x + y
}// 接口定义函数类型
interface Sum{(x:number,y:number):number
}const add: Sum = (x, y) => {return x + y
}// type定义函数类型
type Sum = (x:number,y:number)=>number;
接口继承
interface User {id: number;name: string;
}interface Person extends User {age: number;
}
const Tom:Person = {id: 1,name: 'tom',age: 30
}type Person = User & { age: number }
接口和Type区别?

接口通过interface定义,type是用来定义类型别名。

接口可以重复定义,type不可以。

接口可以继承,type不可以继承,但是可以使用联合类型和交叉类型来模拟继承。

例子:
// 接口.ts
// 1. 定义接口
interface Person {name: stringage: number
}const jack: Person = {name: 'jack',age: 30
}const tom: Person = {name: 'jack',age: 30
}// 2. readonly定义的字段不可修改
// ? 问号字段表示 接口字段可选
interface P {readonly name: stringage?: number
}const lily: P = {name: 'lily'
}// readonly定义的字段不可修改 (报错)
// lily.name = 'Tom'// 3. 定义任意字段的动态属性接口
// >可接收任意字段
// 注意: 任意字段的接口值,应包含父接口的所有类型
interface T {name: stringage: number// 定义动态属性字段[k: string]: string | number// 或者// [k: string]: any
}
const a: T = {name: 'jack',age: 30,id: 1,gender: 'male',edu: '本科'
}// 4. 函数类型接口定义
interface Sum{(x: number, y: number) : number
}
const add:Sum = (x, y) => {return x + y
}// 或者type Sum1 =  (x: number, y: number) => numberconst add1:Sum1 = (x, y) => {return x + y
}// 5. 接口继承与type类型模拟继承
// > 接口可以继承,type不可以继承,但是可以使用联合类型和交叉类型来模拟继承。interface User{id: number;name: string;
}interface Person extends User{age: number
}const zee: Person = {name: "zee",age: 30,id: 1
}// 表示并集,取范围最大的
type Person1 = User & {age : number}const foo: Person1 = {name: "foo",age: 30,id: 1
}type U1 = { id: number; name: string }// 表示或的关系
type Person2 = { age: number } | U1
const tim1: Person2 = {id: 1,name: 'tim',age: 30
}export default {}

六. 泛型三种定义与使用方式

七. 关键知识点 keyof,typeof, in的使用

keyof

JS当中获取key的语法:Object.keys()

TS当中获取key的类型:keyof

interface Person {id: number;name: string;age: number;
}type K1 = keyof Person; // 'id' | 'name | 'age'

通过keyof获取接口的key值, 将其中的key值,组成一个新类型K1,他是一个联合类型

可以将一个变量指定为K1, 他的属性只能为 ‘id’ | 'name | ‘age’,其中之一(字符串)

typeof

实例参考
https://blog.csdn.net/zxl1990_ok/article/details/125474154
对变量使用获取变量类型
对对象使用获取对象类型
对函数使用获取函数类型
对enum使用获取enum类型
对类使用获取类的类型

interface Person {id: number;name: string;age: number;
}cosnt Jack = { id: 1, name: 'jack', age: 30 }type User = typeof Jack;
const Tom:User = { id: 2, name: 'tom', age: 30}

对Jack变量使用typeof,生成一个新类型User,User的定义就是Person类型, 将User类型定义为Tom的类型

in

in 遍历枚举类型
只能在type类型中使用,不能在interface中使用

type Keys = 'id' | 'name' | 'age'type User = {[k in Keys] : any;
}

定义Keys类型 = ‘id’ | ‘name’ | ‘age’
定义类型User,
[k in Keys] : any;
表示,
[k in Keys] : key必需是Keys中的值, ‘id’,‘name’ ,'age’其中一个
any: 值类型,可以是任意类型

例子:
// keyof 获取键值
interface User{id: numbername: stringage: number
}
type Keys = keyof User // keyof 获取键值,生成新类型Keys,赋值给k1
const k1:Keys = 'age'// typeof
// 获取对象类型
const user = {name: 'jack', age: 30}
type User1 = typeof user; // 推断出user对象的类型
// 赋值给新对象定义
const u1:User1 = {name: 'u1', age: 20}// in
// 使原来的任意类型的key,现在只能在指定范围内选interface User2{[k: string]: any
}
// User2,   类型key为string对象,值为任意值// 使原来的任意类型的key,现在只能在指定范围内选
type User3 = {[k in Keys]:any
}
/* 
type User3 = {id: any;name: any;age: any;
}
*/
const tom:User3 = {id: 1,name: 'jack',age: 30,
}export default {}

八.tsconfig.json配置

TypeScript 使用 tsconfig.json 文件作为其配置文件,当一个目录中存在 tsconfig.json 文件,则认为该目录为 TypeScript 项目的根目录。

基础字段
  • files - 设置要编译的文件的名称;[‘./src/main.tsx’]

  • include - 设置需要进行编译的文件,支持路径模式匹配;[‘src’]

  • exclude - 设置无需进行编译的文件,支持路径模式匹配;[‘node_modules’]

  • compilerOptions - 编译配置选项;

编译配置
{"include": ["src/**/*"],"exclude": ["node_modules","**/*.spec.ts"],"compilerOptions": {/* 基本选项 */"target": "es5",                       // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'"module": "commonjs",                  // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'"lib": [],                             // 指定要包含在编译中的库文件"allowJs": true,                       // 允许编译 javascript 文件"checkJs": true,                       // 报告 javascript 文件中的错误"jsx": "preserve",                     // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'"declaration": true,                   // 生成相应的 '.d.ts' 文件"sourceMap": true,                     // 生成相应的 '.map' 文件"outFile": "./",                       // 将输出文件合并为一个文件"outDir": "./",                        // 指定输出目录"rootDir": "./",                       // 用来控制输出目录结构 --outDir."removeComments": true,                // 删除编译后的所有的注释"noEmit": true,                        // 不生成输出文件"importHelpers": true,                 // 从 tslib 导入辅助工具函数"isolatedModules": true,               // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).// 只编译修改过的文件,这个时候会生成tsconfig.tsbuildinfo,下次编译的时候会进行对比只编译修改过的文件 "incremental": true,/* 严格的类型检查选项 */"strict": true,                        // 启用所有严格类型检查选项,不允许隐式any类型"noImplicitAny": true,                 // 在表达式和声明上有隐含的 any类型时报错"strictNullChecks": true,              // 启用严格的 null 检查"noImplicitThis": true,                // 当 this 表达式值为 any 类型的时候,生成一个错误"alwaysStrict": true,                  // 以严格模式检查每个模块,并在每个文件里加入 'use strict'/* 额外的检查 */"noUnusedLocals": true,                // 有未使用的变量时,抛出错误"noUnusedParameters": true,            // 有未使用的参数时,抛出错误"noImplicitReturns": true,             // 并不是所有函数里的代码都有返回值时,抛出错误"noFallthroughCasesInSwitch": true,    // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)/* 模块解析选项 */"moduleResolution": "node",            // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)"baseUrl": "./",                       // 用于解析非相对模块名称的基目录"paths": {},                           // 模块名到基于 baseUrl 的路径映射的列表"rootDirs": [],                        // 根文件夹列表,其组合内容表示项目运行时的结构内容"typeRoots": [],                       // 包含类型声明的文件列表"types": [],                           // 需要包含的类型声明文件名列表"allowSyntheticDefaultImports": true,  // 允许从没有设置默认导出的模块中默认导入。/* Source Map Options */"sourceRoot": "./",                    // 指定调试器应该找到 TypeScript 文件而不是源文件的位置"mapRoot": "./",                       // 指定调试器应该找到映射文件而不是生成文件的位置"inlineSourceMap": true,               // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件"inlineSources": true,                 // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性/* 其他选项 */"experimentalDecorators": true,        // 启用装饰器"emitDecoratorMetadata": true ,         // 为装饰器提供元数据的支持"paths": {"@/*": ["src/*"]}}
}

总结

  • 每一个语法都要手写出来,理解没有偏差。

  • 项目当中反复使用。

  • 工作当中举一反三、活学活用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/590472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 20.04 自由切换 python 的版本

问题描述 当前 ubuntu 20.04 默认安装了多个 python 的版本&#xff0c;执行 python 时&#xff0c;默认版本是 Python 2.7.18 zhangszzhangsz:~$ python Python 2.7.18 (default, Jul 1 2022, 12:27:04) [GCC 9.4.0] on linux2 Type "help", "copyright&quo…

url编码未转义导致参数丢失

原来的请求&#xff1a; "&url${ctx}/loanform/risk/loanItemRiskItemReport/main.ht?baseProductType${baseProductType}""&itemReportId"itemReportId修改后&#xff1a; 原因&#xff1a;请求地址拼接时&#xff0c;会判断name为url的属性是…

多模态大模型的前世今生

1 引言 前段时间 ChatGPT 进行了一轮重大更新&#xff1a;多模态上线&#xff0c;能说话&#xff0c;会看图&#xff01;微软发了一篇长达 166 页的 GPT-4V 测评论文&#xff0c;一时间又带起了一阵多模态的热议&#xff0c;随后像是 LLaVA-1.5、CogVLM、MiniGPT-5 等研究工作…

Impala4.x源码阅读笔记(三)——Impala如何管理Iceberg表元数据

前言 本文为笔者个人阅读Apache Impala源码时的笔记&#xff0c;仅代表我个人对代码的理解&#xff0c;个人水平有限&#xff0c;文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解&#xff0c;欢迎指正。 上一篇文章Impala4.x源码阅读笔记&#xff0…

simulink代码生成(五)——ePWM模块初级应用

前面分别讲到了SCI及ADC的配置及使用&#xff0c;现在梳理一下ePWM的配置和使用&#xff1b; 先打一些基础的DSP28335的基础知识&#xff1b; F28335 关于ePWM中断与SOC采样信号的一些思考_socasel-CSDN博客 F28335 ePWM模块简介——TMS320F28335学习笔记&#xff08;四&…

软件开发必知必会的计算机基础

1.计算机基本介绍 1.1 什么是计算机 计算机(Computer)俗称为电脑&#xff0c;计算机是一种高速计算的电子机器&#xff0c;计算机可以进行数值运算&#xff0c;逻辑判断&#xff0c;接收或者是存储信息数据(文本、图片、音频、视频)&#xff0c;按照存储在其内部的程序对海量的…

5.微服务代码模型

1.微服务代码模型 代码分层 在微服务代码模型里&#xff0c;我们分别定义了用户接口层、并分别为它们建立了interfaces、application、domain和infrastructure四个一级代码目录&#xff1b; interfaces(用户接口层): 它主要存放用户接口层与前端应用交互、数据转换和交互相关…

Ultra ISO 虚拟光驱修改光盘盘符

windows xp 环境 ultra iso 虚拟光驱修改光盘盘符 method 1. 在ultra iso 中 [选项]->[配置]->[虚拟光驱]&#xff0c;在新盘符里选指定盘符 ->[修改] method 2. 打开命令行&#xff0c;进入安装目录&#xff0c;如 "C:\Program Files\UltraISO\drivers"&…

Vue3复习笔记

目录 挂载全局属性和方法 v-bind一次绑定多个值 v-bind用在样式中 Vue指令绑定值 Vue指令绑定属性 动态属性的约束 Dom更新时机 ”可写的“计算属性 v-if与v-for不建议同时使用 v-for遍历对象 数组变化检测 事件修饰符 v-model用在表单类标签上 v-model还可以绑定…

【LMM 002】大型语言和视觉助手 LLaVA-1.5

论文标题&#xff1a;Improved Baselines with Visual Instruction Tuning 论文作者&#xff1a;Haotian Liu, Chunyuan Li, Yuheng Li, Yong Jae Lee 作者单位&#xff1a;University of Wisconsin-Madison, Microsoft Research, Columbia University 论文原文&#xff1a;htt…

JavaScript的三种引入的方式

目录 (一).什么是JS1.1JS的特点1.2JS的组成 (二).JS引用的三种方式2.1标签引用&#xff08;或嵌入式)2.2文件引用&#xff08;外链式&#xff09;2.3行内式 (三).JS三种引用方式的优缺点1.行内方式&#xff1a;2.标签引用&#xff08;或嵌入式&#xff09;&#xff1a;3.文件引…

如何高效查询文件:Linux 下的多种方法详解

如何高效查询文件&#xff1a;Linux 下的多种方法详解 在日常工作中&#xff0c;我们经常需要查找文件&#xff0c;无论是寻找特定的代码文件、配置文件还是其他文档。Linux 提供了多种强大的命令和工具&#xff0c;通过巧妙地使用管道符&#xff0c;我们可以将这些命令组合起来…

连锁门店管理需要信息化系统

连锁门店管理的信息化系统可以提供以下功能&#xff0c;以满足连锁企业日常管理的需求&#xff1a; 1. 连锁线下收银&#xff1a;信息化系统可以提供线下收银功能&#xff0c;包括商品扫码、价格结算、支付方式选择等。通过系统记录每笔交易数据&#xff0c;方便对销售情况进行…

【基于VirtualBox及openEuler20.03 TLS SP1编译openGauss2.1.0源码】

【openEuler 20.03 TLS编译openGauss2.1.0源码】 一、安装环境二、安装步骤 一、安装环境 项目Value虚拟机virtualbox操作系统openEuler 20.03 TLSopenGauss2.1.0openGauss-third_party2.1.0 二、安装步骤 以下操作需要在root用户下执行 编辑/etc/selinux/config vim /etc/s…

C++程序编译

GCC编译器 文章目录 GCC编译器 源文件 为 Main.cpp 注意cpp文件 一定要用g命令 否则没办法执行 预处理&#xff08;Pre-Processing&#xff09;&#xff1a;首先会经过预处理器将程序中的预编译指令进行处理&#xff0c;然后把源文件中的注释这些没用的东西都给扬了。 g -E Mai…

Qt6.5示例:QMainWindow集成QMenuBar菜单栏

欢迎关注公众号(20YC编程)&#xff0c;有免费C视频课程哦&#xff01; -今日内容- 1 QMenuBar简介 QMenuBar是Qt框架中的一个菜单栏类&#xff0c;它提供了一个可以包含一个或多个QAction对象或级联的QMenu对象的菜单栏。 QMenuBar通常被放置在主窗口的标题栏下方&#xff0…

消息队列LiteQueue

文章目录 一、简介二、设计2.1 队列结构设计2.2 队列接口设计 三、实现3.1 队列锁的实现3.2 创建队列3.3 写入队列3.4 读出数据3.5 判断队列是否为空3.6 判断队列是否为满3.7 清空队列3.8 删除队列 四、测试参考 一、简介 收到消息时先把接收到的消息放到队列中。在任务中从队…

63页!嵩山版Java开发手册分享

作为广受欢迎的编程语言之一&#xff0c;Java在软件开发领域扮演着重要的角色。然而&#xff0c;由于Java的灵活性和广泛应用&#xff0c;很容易出现代码质量低下、可读性差、维护困难等问题。为了解决这些问题&#xff0c;阿里巴巴集团发布了一份权威指南——阿里嵩山版Java开…

【2023年第十三届APMCM亚太地区大学生数学建模竞赛】A题 水果采摘机器人的图像识别 35页论文及python代码

【2023年第十三届APMCM亚太地区大学生数学建模竞赛】A题 水果采摘机器人的图像识别 1 题目 水果采摘机器人的图像识别 中国是世界上最大的苹果生产国&#xff0c;年产量约为3500万吨。与此同时&#xff0c;中国也是世界上最大的苹果出口国&#xff0c;世界上每两个苹果中就有…

iToF人脸识别

iToF(间接飞行时间)是一种测量光飞行时间的技术,主要应用于人脸识别。 iToF人脸识别技术在哪些场景下会用到 iToF人脸识别技术可以应用于许多场景,以下是一些常见的应用场景: 平安城市:在城市监控系统中,iToF人脸识别技术可以用于实时监控、目标检测和识别,以及异常行为…