TS学习

92 阅读5分钟

1.基本数据类型

  1. 任意类型( any )可以赋值任何变量
  let num: any = 123;
  let str = num;
  1. unkonw 实际上就是一个类型安全的 any ,但不能直接赋值给其他变量
  let test: unknown;
  let num = 123;
  num = str; //str = w; 赋值报错 


  赋值解决方法

  if (typeof test === 'number') {
    num = test;
  }

  num = test as number

  num = <number> test;
  1. void 表示空值或没有值
const sum = (): void=> {
// return undefined
	console.log(122);
};
sum();
  1. never 表示永远不会返回结果 ( 一般用于报错处理 )
const sum = (): never=> {
 throw new Error('报错了!')
};
  1. object 指定对象中可以包含哪些属性及其类型
let json: { name: string, age?: number } //属性名后边加上?问号 表示属性可选
json = { name: 'sunny' }
           
/**
* 定制特殊类型 [propName:string]:any 
* 表示属性名为 string 类型   属性值为任意类型 其他必选值可以定制
**/
      
let json1: { name: string, [propName: string]: any }
json1 = { name: '小明', color: 'red' }  
  1. array 数组
  let list: string[]
  list = ['1', '2', '3'];

  let list1: Array<number>
  list1 = [1, 2, 3];
  1. tuple 元祖 长度固定的数组
  let list: [number, string];
  //第一个元素是number类型 第二个元素是string类型 并且数组长度只能是2位
  list = [123, '123'];
  1. enum 枚举 枚举所有的情况 值为多选一
  enum ColorType {
    red = 1,
    yellow = 2,
    green = 3
  }

  let json: { name: string, age: 18 | 28, color: ColorType };
  json = {
    name: 'sunny',
    age: 18,
    color: ColorType.green
  }
  1. undefined 类型 & null 类型
//默认情况下null和undefined是所有类型的子类型

let num: undefined = undefined
let num: null = null
let num: number | undefined //number 类型也可以是 undefined 类型 或者 null类型
  1. 泛型 在我们类型不明确的时候,整一个变量来表示泛型

泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出

function fn<S, N>(a: S, b: N): N {
  return b;
}
fn<string, number>('小红', 18);

interface Myrule {
  name: string
}

function fn1<T extends Myrule>(a: T): string {
  return a.name;
}

fn1({ name: '111' });

class myClass1<T>{
  name: T;
  constructor(name: T) {
    this.name = name;
  }
}

let test3 = new myClass1<string>('sunny');

2.TypeScript中的函数

函数的定义

  1. 限定函数返回值类型
  function sum(): string {
    return 'hello world' //函数返回值必须为 string 类型
  }
  1. 限定函数的参数类型
  function sum(name: string, age: number) {
    //函数传递的参数类型必须一一对应
  }
  1. 没有返回值
  function sum(): void {

  }
  1. 可选参数
  function sum(name: string, age?: number) {
    // name必传,age可以不传因为有 ? 号 注意:可选参数写在后面 
  }
  1. 默认参数
  function sum(name: string, age: number = 20) {
    // age 如果不传将使用默认值  注意:默认参数放在前面,后面都可以
  }
  1. 剩余参数
  function getInfo(num: number, ...arr: number[]): void {
    arr.forEach(ele => {
      return num += ele
    })
  }
  getInfo(1, 2, 3, 4, 5);// 1 传给了 num, 剩余的参数传给了 arr ,arr是一个数组

函数的定义方式

  1. 函数声明
  function add(name: string) {

  }
  1. 函数表达式
  const getName = function (name: string): string {
    return `我的名字是${name}`
  }
  1. 箭头函数
  const getAge = (age: number): string => {
    return `我今年${age}岁了`
  }

2.接口和类

当一个对象类型被多次使用时,有如下两种方式来来描述对象的类型,以达到复用的目的

  1. 类型别名 type
  2. 接口 interface
interface 接口名  {属性1: 类型1, 属性2: 类型2}
/**
 * 接口名称(比如,此处的 IMyinterface),可以是任意合法的变量名称,推荐以 `I` 开头
 * 接口可以在定义类的时候去限制类的结构
 * 接口只考虑对象的结构,接口中所有的属性不能有实际值
 * 接口中所有的方法都是抽象方法
 * **/
interface IMyinterface {
  name: string,
  length: number
}

interface IMyinterface {
  color: string,
  like: string
}

let test: IMyinterface = {
  name: 'Bob',
  length: 20,
  color: 'red',
  like: 'baseketball'
}

接口和类型 的区别 interface(接口)和 type(类型别名)的对比:

  • 相同点:
  1. 都可以给对象指定类型
  • 不同点:
  1. 接口,只能为对象指定类型。它可以继承。
  2. 类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名

先有的 interface 后有的 type 推荐使用 type

// 接口的写法-------------
interface IPerson {
	name: string,
	age: number
}

const user:IPerson = {
	name: 'Bob',
	age: 23
}

// type的写法-------------
type Person  = {
	name: string,
	age: number
}
const user2:Person = {
	name: 'Bob',
	age: 23
}

属性

使用static开头的属性是静态的可以通过类去直接访问 Father.age

使用readonly开头的属性表示是一个只读的属性不可更改

方法

使用static开头的方法是静态的可以通过类去直接访问 Father.sum()

class Father {
	readonly name: string = 'sunny'; //只读属性
	static readonly age: number = 23; //静态只读属性
  static sum() {
    console.log('这个是实例方法啦!!!');
  }
}

属性的封装

/**
 * public 修饰的属性可以任意访问更改 默认值
 * private 私有属性只能在类内部访问修改,通过类添加的方法使得私有属性可以被外部访问修改   getter setter 属性的存取器
 * protected 属性可以在自身类以及子类中通过存取器访问修改
 * **/

interface IPerson {
  name: string,
  say(): void
}

class myClass implements IPerson {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  say(): void {
    console.log('实现接口的属性');
  }
}

写法1:
class Person {
  private name: string;
  private age: number;
  protected color : string;
  constructor(name: string, age: number, color:string) {
    this.name = name;
    this.age = age;
    this.color = color;
  }
  get _name() { 
    return this.name;
  }
  set _age(value: number) { //test2._age = 12;
    this.age = value;
  }
  get _color(){
    return this.color;
  }
}

写法2:
class Person {
  constructor(
    private name: string, 
    private age: number, 
    protected color: string
  ) {
  }
...
}

let test2 = new Person('小明', 22, 'red');

class Son extends Person {
  getcolor() {
    console.log(this.color);
  }
}
let son = new Son('孙子', 22, 'green')
console.log(son.getcolor()); //green

ts文件配置

tsc -- init 生成 tsconfig.json

{
	"include": ["./src/**/*"] 指定哪些文件需要编译
  "exclude":[".src/hello/**/*"] 指定哪些文件不需要编译 有默认值
  "flies":["a.tsx ,b.tsx"] 指定单个文件编译
  "compilerOptions": {
    "target": "es2015", 指定ts编译为js的版本
    "module": "es2015", 指定模块化使用的规范
    "lib": "dom", 指定使用的库,一般不填
    "outDir": "./dist" 指定编译后文件所在的目录
    "outFile": "./dist/app.js" 设置outFile之后,所有全局作用域的代码合并到一个文件中,配合module使用
    "allowJs": false 是否对js文件进行编译
    "checkJs":false 是否对js文件进行检查
    "removeComments": false 是否移除注释
    "noEmit" : true 是否生成编译文件
    "noEmitOnError": true 发生错误是否生成编译文件
    
    "strict":true 严格检查的总开关
    "alwayStrict":true 开启严格模式
    "noImplicitAny":true 不允许隐式的any类型
    "noImpliciThis":true 不允许不明确类型的this
    "strictNullChecks":true 严格检查空值
  }
}