入个TypeScript的门(1)——基本数据类型

48 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

TypeScript的火爆是必然的,现在已经成为了前端工程师必须要学会的技能了。的确,它也很香,尤其是在用的时候,当大佬们都把类型和组件等等定义好后,我们在使用这个组件的时候,鼠标移上去就知道这个组件需要哪些参数,这个参数的名称和类型等等。所以现在只会JS是不行啦,得要学学TS啦~

TS的类型

多的不说,TS的优势啥的、咋安装的就省略了,直接进入正题。

我们知道JS有八大类型:String、Number、Boolean、Symbol、Null、Undefined、Object、Bigint。而TS最终也会编译成为JS,那么TS按道理来说也应该只有这八大类型,但是TS再此基础上还多加了很多类型。比如:Never、Void、Any,而且数组中还多了元组。

String、Number、Boolean、Symbol和BigInt

TS的这三个原始数据类型没啥说的,使用也很简单,语法就是:

let str:string = 'string';
let bool:boolean = true;
let num:number = 1;

当然我们也可以不声明类型,ts有个强大的功能就是会自动帮我们推导类型。此外,当我们声明类型后,这个变量就只能被赋值或者修改为这个类型了。

会报错:

let str:string = 'string';
let bool:boolean = true;
let num:number = 1;
 
str = 2;   // 不能将类型“number”分配给类型“string”。
bool = 'aa';   //不能将类型“string”分配给类型“boolean”。
num = false;   // 不能将类型“boolean”分配给类型“number”。

而symbol与bigInt与他们是差不多的:

let a:symbol = Symbol();
   let b:bigint = BigInt(1)

数组

在JS中我们可以在数组中想存什么类型值就存什么类型值,但是在TS中,我们数组如果声明了类型,那么这个数组就只能存声明的类型的值了。

let arr:string[] = ['1','2'];

这时候我们arr就只能存string类型的值了,如果我们存其他类型的,那么就会报错:

arr.push(1);  //类型“number”的参数不能赋给类型“string”的参数。

那么如果我们要存多个类型的值咋办?TS提供了|这个东西,我们可以叫他为‘或’。

let arr:(string|number)[] = ['1','2'];
arr.push(1);

这里的意思就是arr数组的类型可以是string或者number类型,这样就不会报错了。

元组类型

  • 元组的特点就是固定长度、固定类型、固定顺序的一个数组
  • 取值的时候只能通过已有的属性取值
  • 元组可以用数组的push方法追加值,但是你通过索引是取不到你追加的这个值,因为规定不能通过不安全的手段来取值

简单来说他就是类似我们在js中使用const来声明的值,一旦声明了就不可以改变了。

let tuple:[number,string] = [1,'2'];

它的意思就是tuple数字的第一项只能是number类型,而第二项只能是string类型。

console.log(tuple[1]);

我们可以取已有的值。我们再尝试追加值然后取值:

  let tuple: [number, string] = [1, "2"];
  console.log(tuple[1]);
  tuple.push(true);   //类型“boolean”的参数不能赋给类型“string | number”的参数。
  tuple.push(2);    
  console.log(tuple[2]);  //长度为 "2" 的元组类型 "[number, string]" 在索引 "2" 处没有元素。

null与undefined

在非严格模式下,null和undefined可以互相赋值,严格模式下null只能给null,undefined给undefined。

 let nul:null = null;
 let und:undefined = undefined;
 nul = undefined;
 und = null;

但是如果开启严格校验的话(TS配置默认没开启),那么上面代码会报错,说不能将类型“undefined”分配给类型“null”。不能将类型“null”分配给类型“undefined”。

void

void类型是TS新增的,它的含义表示没有任何类型,它的值可以是null、undefined这两种之一。

   let nu:void = undefined;
   nu = null;

但是要注意,如果是严格模式的话,void只能是undefined类型,不能是null类型。

此外,void广泛用于函数中,用于表面函数没有返回值(也就是返回undefined)。

 let fn = (a:number):void=>{
    console.log(a);
 }

never

never也是TS新增的,never类型表示值的类型从不出现。它的特点:

  • 永远没有返回值(void其实是返回undefined的,只是那是默认返回的不是我们返回的)
  • 或者永远会抛出错误
  • never是任何类型的子类型,可以赋值给任何类型
  • 没有类型是never的子类型或能赋值给never(never类型本身除外
// 永远没有返回值
const add: ()=>never = () => {
        while(true){
            console.log(1);
         }
}
//永远抛出一个错误
const fn: ()=>never = () => { throw new Error('error') }

此外never还可以用于缩窄类型,有时候在声明接口或者类型的时候常常用never类型来占位,然后再合并。(因为never类型不会引起类型扩张)

Object

Object中的数组我们已经说了,而对象的话我们就可以这样用:

let obj:object = {}

但是我们很少这样用,因为这个object没啥用,因为它没啥提升,就提示一个object,里面的属性也没有。

Function

关于函数,在TS中就的声明函数的参数类型以及返回值:

function add(x:number,y:number):number {
    return x+y;
}

当然我们还可以定义箭头函数:

const add:(x:number,y:number)=>number =  (x:number,y:number):number=>  x+y

箭头函数唯一的麻烦的地方就是她得去定义类型两次。更多关于函数的知识我们后面再结合type和interface来写。

any与unknow

最后一个就是any与unknow了,他们都是最顶级的类型,就是他们包含所有其他的类型。不过他们俩之间也是有一些差别的。

any它的意思是任意类型,一旦写了any后,那么TS的校验就失效了,相当于没有了类型推断。所以不太建议写any(有一说一,我用的any蛮多的,后面要改)。而unknown类型相较于any更加严格,在执行大多数操作之前,会进行某种形式的检查。

let foo: any = 123;
console.log(foo.msg); // 符合TS的语法
let a_value1: unknown = foo;   // OK
let a_value2: any = foo;      // OK
let a_value3: string = foo;   // OK


let bar: unknown = 222; // OK 
console.log(bar.msg); // Error
let k_value1: unknown = bar;   // OK
let K_value2: any = bar;      // OK
let K_value3: string = bar;   // Error
  • foo是any类型,任何操作都是没有类型检查的,因此对其进行任意类型的赋值都是合法的
  • bar是unknown类型,因此不能确定是否有msg属性,不能通过语法检查,同时unknown类型的值也不能赋值给any和unknown以外的类型变量

同时,unknow会吸收任何类型。即如果任一组成类型是unknown,联合类型也会相当于unknown

type UnionType1 = unknown | null;       // unknown
type UnionType2 = unknown | undefined;  // unknown
type UnionType3 = unknown | string;     // unknown
type UnionType4 = unknown | number[];   // unknown

而any更是能吸收unknown类型,如果任一组成类型是any,则联合类型相当于any

type UnionType1 = unknown  | any; // any
type UnionType2 = string   | any; // any
type UnionType3 = number   | any; // any
type UnionType4 = number[] | any; // any

这里的type的意思是定义一个类型,关于类型我们后面在写。好了就到这里吧,写累了...