前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >typeScript学习总结(一)

typeScript学习总结(一)

作者头像
张宗伟 plus
发布2022-10-28 13:36:51
6990
发布2022-10-28 13:36:51
举报
文章被收录于专栏:张宗伟 plus张宗伟 plus

最近在学习typeScript,因为公司估计需要使用。同样是学习笔记,写文章的意图就在于复习总结一下之前的学习,顺带着积累写文章的感觉,在这个人人都是自媒体的时代,也能不被落的太远。

ts简介

ts是拥有类型系统的js的超集,可以编译成js。它有三个特性:

  • 类型检查:在编译代码时,就进行严格的类型检查
  • 语言扩展:除了js语言的最新和未来提案特性,还包括其他语言的特性,如接口、抽象类
  • 工具属性:是指ts不是一门独立的语言,而是像一个工具库

语言类型简介

语言类型分类有两个维度。

一个是分为强类型语言和弱类型语言:

  • 强类型:是指不能随意改变变量的数据类型,除非进行强制类型转换
  • 弱类型:变量可以任意赋值不同数据类型的值,js真是首当其冲

一个是分为静态类型语言和动态类型语言:

  • 静态类型:是指在编译阶段就确定变量的类型
  • 动态类型:是指在运行阶段才确定变量的类型

这里其实可以举个栗子🌰:

代码语言:javascript
复制
// c++
class C {
  public: 
    int x;
    int y;
}
// add function
int add(C a, C b) {
  return a.x + a.y + b.x + b.y
}
// 在针对内存分配时,add函数中的形参在编译时就确定了属性的偏移量,用偏移量代替了属性名访问
// js
class C {
  constructor(x,y){
    this.x = x
    this.y = y
  }
}
// add function
function add(a,b) {
  return a.x + a.y + b.x + b.y
}
// 针对add函数,在编译的时候会存储属性名x、y,并在运行动态计算偏移量

ts数据基本类型

代码语言:javascript
复制
// boolean
let bool: boolean = true
// Number
let num: number = 1
// string
let str: String = 'str'
// Symbol
let sym: Symbol = Symbol()
// null是任何类型的子类型
// null,只能为null
let nul: null = null
// undefined,只能为undefined
let undef: undefined = undefined
// Array,数组还要确保元素的类型
let arr: Array<number> = [1,2,3]
let arr2: number[] = [4,5,6]
// Object
// 这样的方式,不可更改属性的值
let obj: Object = {x:1, y:2}
let obj2: {x: number, y: number} = {x:1, y:2}
// function
let fun = (x: number, y: number) => x+y
// 或者声明返回值类型,但是ts会自动推测
let fun2 = (x: number, y: number): number => x+y
// 还可以先定义,后赋值
let fun3 = (x: number, y: number) => number
// 形参名可以不同
fun3 = (a: number, b:number) => a+b
// 元组tuple,不仅确定了类型还确定了元素数量
let tuple: [number, string] = [1,'2']
// 可以越界添加
tuple.push(3)
// 但是不可以越界访问
tuple[2] // 报错
// any,任何类型,这就和js中定义变量没其他不同了
let any1: any = '1'
any1 = 2
// void,什么类型也不是
// void作为操作符,可以使表达式为undefined
void 1+2 // 输出undefined
// 函数返回值为void
let void_fun = (): void => {}
// 可以被赋值undefined和null(设置strictNullChecks为false)
let unusable = undefined
unusable = null
// never,表示不存在这个类型
// never是任何类型的子类型
let nev = (): never => {
  throw Error("this is a err")
}
let nev2 = (): never => {
  while(true) {}
}
// 联合类型,每种类型都是或的关系
let union: number | string | boolean

ts枚举类型

枚举类型在js中是没有的,是一组具有名称的常量集合。将程序中存在的硬编码或者将来可能改变的常量抽取出来形成一个枚举类型,方便管理。

  • 基于数字的枚举
代码语言:javascript
复制
// 各个属性自0递增
enum Role {
  Developer,
  Reporter,
  Owner,
}
Role.Development // 0
Role.Owner // 2
// 可以自定义指定属性值
enum Role {
  Development=1,
  Reporter,
  Owner,
}
Role.Owner // 3

再者数字枚举,其实是一个对象,符合反向映射,如上面的Role其实是:

  • 基于字符串的枚举
代码语言:javascript
复制
// 字符串枚举
enum Message {
  success='success',
  fail='fail'
}

字符串枚举不会反向映射,如上面的Message:

  • 异构枚举-数字枚举和字符串枚举的混用
代码语言:javascript
复制
enum Answer {
  X,
  Y='No',
  // 注意,Z必须赋初始值
  Z=1,
  H,
}
  • 常量枚举
代码语言:javascript
复制
// 使用const标识符定义
// 在编译时会被移除,只可访问属性,更加节省时间
const enum Info {
  success,
  fail,
}
  • 枚举成员分类
    • const member,在编译时就被计算,如何出现错误就会被赋值为NaN或Infinity。这类成员需满足:未赋初值、赋值为数字或字符串、赋值为已有的成员、普通的表达式
    • computed member,在执行时才被计算,含字符串的枚举不可有此成员。这类成员通常是:arr.length...
  • 将枚举作为一种类型-自定义枚举类型
代码语言:javascript
复制
// 枚举成员未赋初始值
enum E {a,b}
let a: E = 1
let b: E.b = 2
// 枚举成员赋初始值
enum F {a=1, b='str'}
// 注意字符串只能赋已有的值,且如果指定了某个成员类型则必须为这个成员的值
let c: E.b = 'str' // 报错
let d: E.b = E.b // 正确
// 不同类型之间不能进行比较
a === b // 报错

枚举成员是只读属性,不能被赋值。在运行时枚举就是一个对象。

  • 环境枚举
代码语言:javascript
复制
// 和常量枚举的不同点在于未被赋初值的成员会被当作计算值
declare enum Enum {
  x=1,
  y, // 当作计算值
  z=3
}

ts接口类型

使用interface定义,用来约束对象、函数、类的结构和类型。

  • 对象类型接口
代码语言:javascript
复制
interface List {
  // 加上readonly即变为只读属性
  readonly id: number,
  name: string,
  // 加上?就为可选属性
  age?: number,
  // 使用索引
  [x: string]: any
}
let data: List = {
  id: 0,
  name: 'zhangzongwei'
}
let arr: List[] = [
  {id: 0, name: 'duanshuqing'},
  {id: 1, name: 'zhangzongwei', age: 25}
]
// 当不做数据类型约束时可以添加其他未定义的属性,但是不允许访问
let data2 = {
  id: 1,
  name: 'zhangzongwei',
  sex: '男'
}
function render(result: List) {
  console.log(result.id,result.name)
  console.log(result.sex) // 报错
}
// 当添加了其他属性,以下面的方式传入render时,会报错
render(
  {id: 0, name: 'zhangzongwei', sex: '男'}
 )
 // 解决方式:
 // 1. 使用断言,就是确定地告诉ts编译器,我清楚传入的是什么类型
 render(<List>{...})
 render({...} as List)
 // 2. 使用索引,见上面
 // 3. 赋值给一个变量再传入
  • 索引类型

当你不确定对象中有多少个属性的时候,就可以使用索引类型。

代码语言:javascript
复制
// 数字索引
interface Names {
  [x: number]: string
}
let name: Names = ['zhang','zongwei']
// 字符串索引
interface Address {
  [y: string]: string
}
let addr: Address = {
  province: 'henan',
  city: 'xinyang'
}
// 字符串接口有两种访问方式
addr.province
addr['city']
// 两者可以混用,number返回的属性值一定要和string返回的属性值一样
// 因为当通过number索引时,也是先转换为string再去索引,所以返回的属性值类型要相同
interface Info {
  [x: string]: string,
  [y: number]: string
}
  • 函数类型接口
代码语言:javascript
复制
interface render {
  (result: string) => string
}
let ren: render = (x: string) => x
// 也可以不传入参数类型,因为ts会自动推导
let ren2: render = (x) => x
  • 混合接口-不同类型接口的混用
代码语言:javascript
复制
interface Lib {
  (): void,
  version: string,
  getVersion(ver: string): string  
}
let lib: Lib = (() => {}) as Lib
lib.version = '1.0'
lib.getVersion = (ver: string) => ver

参考资源

  • https://www.typescriptlang.org/docs/handbook/interfaces.html
  • https://time.geekbang.org/course/detail/211-108550
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 张宗伟 plus 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档