基础数据联合声明
let value: string | number;
value = 123;
value= "abc";
对象的类型
//例子 --------------------------------------------
interface Person {
readonly id:number;
name:string;
list:number[],//数组声明
list2:Array<string>;//数组声明
age?:number;//可选属性
[proName:string]: any;//任意属性
}
let tom:Person = {
id:3,
name:'Tom',
list:[11,111],
list2:['22','22'],
//age:25,
//gender:'male',
}
//tom.id = 9;//无法为“id”赋值,因为它是只读属性。
//例子 --------------------------------------------
function getData(params:{
name:string;
height:number;
}){
console.log('params: ', params);
}
getData({
name: "Jonh",
height:33,
});
//例子 --------------------------------------------
//vue3
import { ref,reactive } from "vue";
interface T {
total?: number | string | undefined | null;
name: string;
age: number;
}
const count = ref<number>(0); // 任意数据类型的响应式变量
const state = reactive<T>({ total: 5, name: "vue3", age: 18 }); // reactive 多用于响应式对象定义
const arr = reactive<T[]>([//reactive<Array<T>>([])
{ total: 5, name: "vue3", age: 18 },
{ total: 6, name: "react", age: 28 }
]); // reactive 定义数组
arr = [{ total: 5, name: "vue3", age: 18 }];//重新赋值,内存地址改变,失去响应式
const list = ref<T[]>([
{ total: 5, name: "vue3", age: 18 },
{ total: 6, name: "react", age: 28 }
]); // reactive 定义数组
list.value = [{ total: 5, name: "vue3", age: 18 }];//重新赋值,重新进行reactive绑定,响应式保留
数组类型定义。两种写法如下:
//1.数组类型定义有两种
const arr:Array<number> = [1];//泛型的形式
const arr:number[] = [1,2,3];//[]的形式
//2.以上两种定义数组类型的方式虽然本质上没有任何区别,但是我更推荐使用 [] 这种形式来定义。一方面可以避免与 JSX 的语法冲突,另一方面可以减少不少代码量。
//vue3
import { reactive } from "vue";
interface T {
aaa:number,
bbb?:string,
}
let arr = reactive<Array<T>>([{
aaa:999,
bbb:'BBB',
},{
aaa:888,
}]);
let list = reactive<T[]>([{
aaa:11111,
},{
aaa:22222,
}]);
接口【interface】。接口中可定义【确定属性、可选属性、任意属性、只读属性、函数】
//例子 --------------------------------------------
interface Baseinfo {
name:string,
age:string | number | number[] | Array<string> | null | undefined,
sex?:string,//可选类型 -- 用'?'号修饰
[key:string]:any, //可以叫任意名字(key),也可other,aaa,bbb,如[aaa:string]:any。索引签名:可以添加不确定参数
}
let obj:Baseinfo = {
name: "3",
age: [1],
mmm:111,
nnn:222,
}
//例子 --------------------------------------------
interface Point {
readonly x: number;
readonly y: number;
}
// p 是接口Point 类型
let p: Point = { x: 10, y: 20 };
p.x = 5; // error! 已经设置了readonly 属性所以禁止更改
//例子 --------------------------------------------
interface BaseInfo{
name:string,
age:number,
eat(food: string,count?:number | string):string,//定义函数
}
const personInfo:BaseInfo = {
name:'chen',
age:18,
eat(parmas,count){
return parmas + count;
},
}
personInfo.eat('苹果',5);
//例子 --------------------------------------------
interface Animal {
type:string;
}
interface Other {
weigth:number;
}
interface Cat extends Animal,Other {//extends继承多个接口
name:string;
}
let cat:Cat = {
name: "猫",
type: "种类",
weigth: 10
}
//例子 --------------------------------------------
interface Girl {
name:string;
age:number;
hobby?:string;
[propName:string]:any;
say():string;
}
class Club implements Girl{
//定义一个类,通过接口interface进行限制
name = '88号小红';
age = 18;
hobby = '教学';
height = 168;
say(): string {
return 'Hello Everybody!'
}
study(type:string):void{
console.log('研究类型',type);
}
}
//例子 --------------------------------------------
// 函数类型的接口:第一种
interface Add{
(x:number,y:number):number
}
// 函数类型的接口:第二种
// type Add = (x:number,y:number) => number
let add:Add = (a,b)=> {
return a+b;
}
//例子 --------------------------------------------
//接口做闭包(混合类型)
interface Counter {
(start: number): string;
total: number;
reset(): void;
}
function getCounter(): Counter {
//let counter = <Counter>function (start: number) { };
let counter:Counter = function (start: number) { } as Counter;
counter.total = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.total = 5.0;
//例子 --------------------------------------------
//接口可以重复定义的接口类型,它的属性会叠加,类型别名不行。两个相同名称的接口会合并声明,定义两个同名的 type 会出现异常。
interface Language {
year: number;
}
interface Language {
name: string;
}
let lang: Language = {
year: 2018,
name: 'TypeScript',
}
//接口交叉。例子 --------------------------------------------
interface Iperson {
name: string;
say(): void;
}
interface Iaction {
run():void
}
// 此时定义的obj是Iperson和Iaction的交叉类型,其中必须包含这两个接口中定义的属性
let obj:Iperson & Iaction = {
name:'陈明',
say() {},
run() {},
}
//例子 --------------------------------------------
interface Iperson {
name: string;
say?(): void;
}
interface Iaction {
speed:number;
run():void;
}
// 联合类型 (只需满足其中一个接口类型所定义的属性)
let obj:Iperson | Iaction = {
name:'陈明',
say() {},
}
function doSomething(params:Iperson | Iaction){
console.log('params: ', params);
}
doSomething({name:'陈明'});
doSomething({speed:20,run:()=>{}});//满足其中一个接口条件就行
接口类型【type】
//(原始)基本类型
type nameType = string;
//联合类型
type paramsType = number | string | boolean;
//元组类型
type arrType = [string, string, number];
//type 支持类型映射,interface不支持
type Keys = "name" | "hobby"
type MapType = {
[key in Keys]: string;
}
const test: MapType = {
name: "小明",
hobby: "打球"
}
//interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说 interface 可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。
//interface 继承 interface ----------------------------
interface Person {
name: string;
}
interface User extends Person {
age: number;
}
//type 继承 type ----------------------------
type Person = {
name: string;
}
type User = Person & { age: number };
//interface 继承 type ----------------------------
type Person = {
name: string;
}
interface User extends Person {
age: number;
}
//type 继承 interface ----------------------------
interface Person {
name: string;
}
type User = Person & {
age: number;
}
注:interface 只能用于定义【对象类型和方法】, type 可以定义【原始(基本)类型、联合、元组、对象、函数、交叉(继承)】等,类型声明的方式适用范围显然更加广泛。
但是interface也有其特定的用处:
interface 方式可以实现接口的 extends 和 implements。
interface 可以实现接口合并声明。
interface接口可以 extends、implements,从而扩展多个接口或类。type类型没有扩展功能,只能交叉合并。
类作为类型【class】
class PersonInfo {
name: string;
age: number;
hobby?:string;
constructor(name: string , age:number) {
this.name = name;
this.age = age;
}
}
const boy1:PersonInfo = {}; //错误提示: Type '{}' is missing the following properties from type 'PersonInfo': name, age
const boy2:PersonInfo = { name: '小明',age:18 };
类型断言【as】。语法:值 as 类型。在浏览器控制台输入HTML,便会提示HTMLElement、HTMLInputElement、 HTMLImageElement 等函数。
let dom = document.getElementById('Id-Name') as HTMLElement;//变量dom指定为html元素
let barElement: HTMLElement = this.$refs.$bar as HTMLCanvasElement;
//例子 --------------------------------------------
let timeInterval: number | null = null;
clearInterval(timeInterval as unknown as number);//双重断言
clearInterval(timeInterval as any);//【any】跳过校验
//例子 --------------------------------------------
let add_0 = (num:number):number | string=>(num > 9 ? num : `0${num}`);
add_0(9);
add_0('4' as unknown as number);//双重断言
add_0(('4' as any) as number);//双重断言
add_0(window.localStorage.getItem("number") as any);//【any】跳过校验
let value:number | undefined;
add_0(value as number);
//例子 --------------------------------------------
function handler(event: Event) {
const element = (event as any) as HTMLElement; //双重断言:让其同时继承两个属性Event、HTMLElement
}
//例子 --------------------------------------------
interface T {
aaa:number,
bbb:string,
ccc?:[],//可能是【数组、undefined】
}
let obj:T = {
aaa: 0,
bbb: "b",
//ccc:[]
}
let arr = obj.ccc as [];//不推荐:强制通过ts校验,ccc可能是【undefined】
//let arr = obj.ccc || [];//推荐
for (let i = 0; i < arr.length; i++) {
const element = arr[i];
}
//例子 --------------------------------------------
interface Foo {
age: number;
name: string;
}
const foo = {} as Foo;//方法一,建议少用
// const foo:Foo = {//方法二,推荐
// age:22,
// name:'hello',
// };
foo.age = 22;
foo.name = 'hello';
//例子 --------------------------------------------
//获取 animal.swim 的时候会报错
//此时可以使用类型断言,将 animal 断言成 Fish
//注意:类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误。类型断言尽量不要滥用,只有当一些复杂情况,TS 不能推断出类型的时候,才用类型断言。
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === 'function') {
return true;
}
return false;
}
枚举 【enum】
//枚举类型
export enum Color {
Red = "#f00",
Blue = "#007ac1",
Pink = 'oxc10050',
White = 255,
}
let red = Color['Red'];
let blue = Color.Blue;
Promise函数,返回值可能是布尔值与字符串。
let getInfoById = (id:number,size = '3',state?:boolean):Promise<boolean | string>=>{
return new Promise((resolve,reject)=>{
if(Math.random()>0.5){
console.log(id,size,state);
resolve(true)
}else{
resolve('出错了!')
}
});
};
getInfoById(88).then(status=>{
if(status){}
});
//写法一:
interface Iparams {
pageSize:number,
pageNo:number,
leval:1 | 2 | 3,
status?:false,
}
let getDataList = (params:Iparams):void=>{
console.log('params: ',params);
}
getDataList({
pageSize: 1,
pageNo: 10,
leval: 1
});
//写法二:
let getDataList = (params:{
pageSize:number,
pageNo:number,
leval:1 | 2 | 3,
status?:false,
}):void=>{
console.log('params: ',params);
}
getDataList({
pageSize: 1,
pageNo: 10,
leval: 3,
});
泛型工具类型
Partial
把已有的类型属性,变成一个新类型的可选属性
语法 : type 新类型 = partial<老类型>
Readonly
把已有类型全部转换为只读类型
语法和上述一直
定义对象使其内在属性不能修改
Pick
从已有类型中选一些属性来构造新的类型
语法 : type 新类型 = partial<老类型,属性|属性2>
typescript官网/其它网站: