TS操作基础手册(内含vue3.0示例)

本文只对常用的ts语法进行推荐,其他的语法根据自己需要,自行学习剖析

安装

使用npm全局安装typescript

(如果出现报错,大概率是因为权限不够导致的,使用管理员权限进行安装)

npm i -g typescript

运行

将ts文件生成为对应的js文件

(node无法直接运行ts文件,所以如果用node运行,要用下面的命令先生成js文,如针对test.ts使用如下命令,可自动生成test.js的文件)

tsc test.ts

node运行ts文件

ts-node test.ts

简单数据类型

简单数据类型number约束

let decimal: number = 6;

简单数据类型boolean约束

let isDone: boolean = false;

简单数据类型string约束

let color: string = "blue";

任意类型或未知

any数据类型,慎用,一般不推荐使用,使用any会失去类型校验

let d: any = 4;

unknown数据类型,可以理解为安全的any,不推荐使用

let notSure: unknown = 4;

复杂类型

复杂类型数组校验

let list: number[] = [1, 2, 3];
或者 
const list:Array<number> = [1,2,3]

enum,枚举,TS中新增类型

enum Color {
  Red,
  Green,
  Blue,
}

let c: Color = Color.Green;

void类型,多用于函数无返回值的情况

function handleAdd(num1:number,num2:number):void {
	this.sum =num1+num2
}

定义对象其余所有参数,如下,obj里除name为string外,其余参数键为字符串,值为number类型

let obj:{name:string,[propName:string]:number}

类型断言

对于一个数据,可能为多个类型或者未知类型的时候,但是我们只需要特定的类型的属性时,进行断言,断定为我们需要的类型

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

非空断言

在上下文中当类型检查器无法断定类型时,可以使用操作符 ! 进行断言操作对象是非 null 和非 undefined 的类型,即x!的值不会为 null 或 undefined

  let user: string | null | undefined;
  console.log(user!.toUpperCase()); // 编译正确
  console.log(user.toUpperCase()); // 错误

确定赋值断言

let value:number
console.log(value); // Variable 'value' is used before being assigned.

我们定义了变量, 没有赋值就使用,则会报错

通过 let x!: number; 确定赋值断言,TypeScript 编译器就会知道该属性会被明确地赋值。


类class (用到的开发场景不多,建议只做了解)

定义类

class 类名 {
	属性名: 类型;
	
	constructor(参数: 类型){
		this.属性名 = 参数;
	}
	
	方法名(){
		....
	}
}

示例:

class Person{
    /*
     * public(默认值),可以在类、子类和对象中修改,可省略
     * protected ,可以在类、子类中修改
     * private ,可以在类中修改
     */
  public name: string;
  public age: number;

    constructor(name: string, age: number){
        this.name = name;
        this.age = age;
    }

    sayHello(){
        console.log(`大家好,我是${this.name}`);
    }
}
//继承
class Employee extends Person{
    constructor(name: string, age: number){
        super(name, age);
        this.name = name; //只有父类数据为public或者protected,子类中可以修改父类数据
    }
}

//使用类
const p = new Person('孙悟空', 18);
p.sayHello();

抽象类

抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例

使用abstract开头的方法叫做抽象方法,抽象方法没有方法体只能定义在抽象类中,继承抽象类时抽象方法必须要实现

abstract class Animal{
    abstract run(): void;
    bark(){
        console.log('动物在叫~');
    }
}

class Dog extends Animals{
    run(){
        console.log('狗在跑~');
    }
}

接口(Interface)

示例(检查对象类型):

interface Person{
    name: string;
    sayHello():void;
}

function fn(per: Person){
    per.sayHello();
}

fn({name:'孙悟空', sayHello() {console.log(`Hello, 我是 ${this.name}`)}});

type 类型别名

type myType = string|number;
type menuListType={
	menuId:number;
	meuName:syring
}
interface dataType {
	menuList:menuListType[]
}

let m:myType
const data:dataType = {
	menuList:[],
	userInfo:[]
}

 interface 和 type的异同

接口和类型别名都可以用来描述对象或函数的类型,只是语法不同

type MyTYpe = {
  name: string;
  say(): void;
}
​
interface MyInterface {
  name: string;
  say(): void;
}

相同点:

都允许扩展

interface 用 extends 来实现扩展;type 使用 & 实现扩展

interface MyInterface {
  name: string;
  say(): void;
}
​
interface MyInterface2 extends MyInterface {
  sex: string;
}
​
type MyType = {
  name:string;
  say(): void;
}
type MyType2 = MyType & {
  sex:string;
}
​
let person:MyInterface2 = {
  name:'小明',
  sex:'男',
  say(): void {
    console.log("hello 啊,小明!");
  }
}
​
​
let value: MyType2 = {
  name:'小明',
  sex:'男',
  say(): void {
    console.log("hello 啊,小明!");
  }
}

不同点

type可以声明基本数据类型别名/联合类型/元组等,而interface不行

// 基本类型别名
type UserName = string;
type UserName = string | number;
// 联合类型
type Animal = Pig | Dog | Cat;
type List = [string, boolean, number];

interface能够合并声明,而type不行

interface Person {
  name: string
}
interface Person {
  age: number
}
// 此时Person同时具有name和age属性

联合类型

联合类型用|分隔,表示取值可以为多种类型中的一种

let name:string|number
status='小虾米'
status=100

交叉类型

交叉类型就是跟联合类型相反,用&操作符表示,交叉类型就是两个类型必须存在

注意:交叉类型取的多个类型的并集,但是如果key相同但是类型不同,则该key为never类型

interface PersonA{
  name: string,
  age: number
}
interface PersonB {
  name: string,
  gender: string
}
//person 即是 PersonA 类型,又是 PersonB 类型
let person: PersonA & PersonB = { 
    name: "龟仙人",
    age: 88,
    gender: "男"
};

类型守卫

类型守卫是运行时检查,确保一个值在所要类型的范围内

目前主要有四种的方式来实现类型保护:

in 关键字

interface InObj1 {
    a: number,
    x: string
}
interface InObj2 {
    a: number,
    y: string
}
function isIn(arg: InObj1 | InObj2) {
    // x 在 arg 打印 x
    if ('x' in arg) console.log('x')
    // y 在 arg 打印 y
    if ('y' in arg) console.log('y')
}
isIn({a:1, x:'xxx'});
isIn({a:1, y:'yyy'});

typeof 关键字

function isTypeof( val: string | number) {
  if (typeof val === "number") return 'number'
  if (typeof val === "string") return 'string'
  return '啥也不是'
}

instanceof关键字(作了解)

function creatDate(date: Date | string){
    console.log(date)
    if(date instanceof Date){
        date.getDate()
    }else {
        return new Date(date)
    }
}

自定义类型保护的类型谓词(作了解)

function isNumber(num: any): num is number {
    return typeof num === 'number';
}
function isString(str: any): str is string{
    return typeof str=== 'string';
}

泛型(Generic)

定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。

这里的<T,K>就是泛型,T是我们给这个类型起的名字(不一定非叫T或者K),设置泛型后即可在函数中使用T或者K来表示该类型。所以泛型其实很好理解,就表示某个类型。即:传入的是什么类型,那泛型就是什么类型

function test<T, K>(a: T, b: K): K{
    return b;
}
test<number, string>(10, "hello");

泛型接口

在定义接口的时候指定泛型

interface KeyValue<T,U> {
  key: T;
  value: U;
}

const person1:KeyValue<string,number> = {
  key: '小明',
  value: 18
}
const person2:KeyValue<number,string> = {
  key: 20,
  value: '张麻子'
}

泛型类

class Test<T> {
  value: T;
  add: (x: T, y: T) => T;
}
​
let myTest = new Test<number>();
myTest.value = 0;
myTest.add = function (x, y) {
  return x + y;
};

泛型类型别名

type Cart<T> = { list: T[] } | T[];
let c1: Cart<string> = { list: ["1"] };
let c2: Cart<number> = [1];

泛型参数的默认类型

我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

function createArray<T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}

泛型工具类型

typeof 推出类型

//先定义变量,再定义类型
let p1 = {
  name: "小明",
  age: 18,
  gender: "male",
};
type People = typeof p1;
function getName(p: People): string {
  return p.name;
}
getName(p1);

keyof 可以用来获取一个对象接口中的所有 key 值

interface Person {
  name: string;
  age: number;
  gender: "male" | "female";
}
​
type PersonKey = keyof Person; //type PersonKey = 'name'|'age'|'gender';
​
function getValueByKey(p: Person, key: PersonKey) {
  return p[key];
}
let val = getValueByKey({ name: "小明", age: 18, gender: "male" }, "name");
console.log(val); // 小明

in 用来遍历枚举类型:

type Keys = "a" | "b" | "c"
​
type Obj =  {
  [p in Keys]: any
} // -> { a: any, b: any, c: any }

extends 对泛型的范围进行约束,泛型T必须是MyInter的子类,不一定非要使用接口类,抽象类同样适用。

//现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
interface MyInter{
    length: number;
}
​
function test<T extends MyInter>(arg: T): number{
    return arg.length;
}
​
test(3);// Error, number doesn't have a .length property
​
​
test({length: 10, name: '张麻子'}); // 当我们传入合法的类型的值,即包含 length 属性的值时,编译正确

infer 在条件类型语句中,可以用 infer 声明一个类型变量并且对它进行使用。(了解)

//infer R 就是声明一个变量来承载传入函数签名的返回值类型,简单说就是用它取到函数返回值的类型方便之后使用。
type ReturnType<T> = T extends (
  ...args: any[]
) => infer R ? R : any;
使用 [] 操作符可以进行索引访问:

interface Person {
  name: string;
  age: number;
}
​
type x = Person["name"]; // x is string

TS中常用的高级内置工具类型

Partial集体可选(将类型定义的所有属性都修改为可选。)(重点

  checkInData: Partial<{
    today_sign: number;
    series_days: number;
  }>;
  
  上面的代码相当于
   checkInData:{
    today_sign?: number;
    series_days?: number;
  } 

Record 简单对象键值对,所有类型指定(重点

以 typeof 格式快速创建一个类型,此类型包含一组指定的属性且都是必填。

//示例1,对象的键必须为'x'或者'y',键值必须为数字类型:
type Coord = Record<'x' | 'y', number>;
​
// 等同于
type Coord = {
    x: number;
    y: number;
}
//示例2:
//activity对象,第一个参数为key,必须为字符串,第二个参数为key值,必须为数字
activity: Record<string, number>;

Readonly 将所有属性定义为只读(重点

type Coord = Readonly<Record<'x' | 'y', number>>;
​
// 等同于
type Coord = {
    readonly x: number;
    readonly y: number;
}
​
// 如果进行了修改,则会报错:
const c: Coord = { x: 1, y: 1 };
c.x = 2; // Error: Cannot assign to 'x' because it is a read-only property.

pick 选取部分类型校验(重点

如下:CoordX选取了Coord中的x组成一个新的type数据类型校验

type Coord = Record<'x' | 'y', number>;
type CoordX = Pick<Coord, 'x'>;
​
// 等用于
type CoordX = {
    x: number;
}

Omit 与Pick相反,Omit<T,K> 从T中取出除去K的其他所有属性。

interface Person {
  name: string,
  age: number,
  gender: string
}
type P1 = Omit<Person, "age" | "gender">
const user:P1  = {
  name: '小明'
}

Required 集体必选(重点

interface Person {
    name?: string,
    age?: number,
    hobby?: string[]
}
​
const user: Required<Person> = {
    name: "小明",
    age: 18,
    hobby: ["code"]
}

InstanceType 返回构造函数类型C的实例类型,常用于获取组件实例

class C {
  x = 0;
  y = 0;
}
​
type D = InstanceType<typeof C>;  // C

Exclude 将某个类型中属于另一个的类型移除掉,剩余的属性构成新的类型

type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number

Extract 和 Exclude 相反,Extract<T,U> 从 T 中提取出 U。适用于:并集类型 (了解)

type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () =>void

NonNullable 去除类型中的 nullundefined (了解)

type P1 = NonNullable<string | number | undefined>; // string | number
type P2 = NonNullable<string[] | null | undefined>; // string[]

ReturnType 用来得到一个函数的返回值类型 (了解)

type Func = (value: string) => string;
const test: ReturnType<Func> = "1";

Parameters 用于获得函数的参数类型所组成的元组类型。(了解)

type P1 = Parameters<(a: number, b: string) => void>; // [number, string]

以下为TS+vue3的部分开发语法

详情请移步至vue3.0+TS文章查看:vue3.0+TS使用_零凌林的博客-CSDN博客

ts+ref

const show = ref<boolean>(false);

ts+reactive

type menuListType={
	menuId:number;
	meuName:syring
}
interface dataType {
	menuList:menuListType[]
}

const data =reactive<dataType>({
	menuList:[],
	userInfo:[]
})
或者
const data:dataType =reactive({
	menuList:[],
	userInfo:[]
})

获取组件 ref 实例+ts

使用 vue3 和 ts 时,为了获取 组件 ref 实例,就需要在 ref 函数的泛型中指定类型。如何获取组件的类型呢?vue 官方文档中 TypeScript 支持里已经告诉我们了一个获取组件类型的方法,InstanceType<typeof 组件名称>,使用方式如下:

const $userForm = ref<InstanceType<typeof userForm>>();

ts ref实例

//子组件
<NewsDialog ref="news" @refreshData="getList()"></NewsDialog>
//导入子组件
import NewsDialog from './components/NewsDialog.vue'
//获取子组件实例
const news = ref<InstanceType<typeof NewsDialog>>()            
//打开消息弹窗
const openNewsDialog = (): void => {
  news.value?.showDialog()
}

获取原生dom的ref实例

//input标签 
<input
  type="text"
  class="search"
  ref="input"
  v-model="inputValue"
  placeholder="队伍名称最多6个字"
  maxlength="6"
/>
 
const input = ref<HTMLElement | null>(null); 
//获取焦点
(input.value as HTMLInputElement).focus();

ts结合emit使用

//之前的写法
const emit = defineEmits(['change', 'update'])
//ts写法
const emit = defineEmits<{
	(e:'change'):void,
	(e:'update',value:string):void
}>

ts结合prop使用

//之前的写法
const prop = defineProps({
    id:{
        type:Number,
        default:0
    }
})
//ts写法
interface PropType = {
    id:number
}
const prop = defineProps<PropType>()

tips:以下作为了解,当我们使用vant组件库官方推荐的自动引入组件的方法时需注意:

Vant 中有个别组件是以函数的形式提供的,包括 Toast,Dialog,Notify 和 ImagePreview 组件。在使用函数组件时,unplugin-vue-components 无法自动引入对应的样式,因此需要在需要的页面里手动引入样式。

import { Dialog } from 'vant';
const VanDialog = Dialog.Component;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零凌林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值