Ts:是TypeScript的简称,是一种由微软开发的自由和开源的编程语言。
npm install -g typescript
//或
yarn global add typescript
tsc -v //查看版本
在线编译:https://www.typescriptlang.org/play
//字符串
let str: string = "Domesy"
// 数字
let num: number = 7
//布尔
let bool: boolean = true
//symbol
let sym: symbol = Symbol();
//bigint 用来表示那些已经超出了 number 类型最大值的整数值,对于总是被诟病的整数溢出问题,使用了 bigint 后将完美解决
let big: bigint = 10n
//null
let nu: null = null
//undefined
let un: undefined = undefined
Array 两种方式
let arr1:number[] = [1,2,3]
let arr2:Array = [1,2,3]
let arr3:Array = [1,2,'3'] // 报错
let arr4:Array = [1,2,'3']
Tuple(元组)
Tuple可以说是Array的一种特殊情况,针对上面的arr3,类型是string或者number,但对每个元素没有做出具体的限制。
Tuple 的作用就是限制元素的类型并且限制个数的数组,同时 Tuple这个概念值存在于TS,在JS上是不存在的
注意:在ts中,是允许对Tuple扩增(数组的push),但在访问上不允许。
let t: [number, string] = [1, '2'] // ok
let t1: [number, string] = [1, 3] // error
let t2: [number, string] = [1] // error
let t3: [number, string] = [1, '1', true] // error
let t5: [number, string] = [1, '2'] // ok
t.push(2)
console.log(t) // [1, '2', 2]
let a = t[0] // ok
let b = t[1] // ok
let c = t[2] // error
object
let obj1:object={
a: 1,
b: 2
}
obj1.a = 3 // error
let obj2: { a: number, b: number } = {
a: 1,
b: 2
}
obj2.a = 3 // ok
let obj: Object;
obj = 1; // ok
obj = "a"; // ok
obj = true; // ok
obj = {}; // ok
obj = Symbol() //ok
obj = 10n //ok
obj = null; // error
obj = undefined; // error
function
定义函数
function setName1(name: string) { //ok
console.log("hello", name);
}
setName1("Domesy"); // "hello", "Domesy"
function setName2(name: string):string { //error 函数没有返回值
console.log("hello", name);
}
setName2("Domesy");
function setName3(name: string):string { //error 函数的返回值是 number
console.log("hello", name);
return 1
}
setName3("Domesy");
function setName4(name: string): string { //ok 函数的返回值是string
console.log("hello", name);
return name
}
setName4("Domesy"); // "hello", "Domesy"
//箭头函数与上述同理
const setName5 = (name:string) => console.log("hello", name);
setName5("Domesy") // "hello", "Domesy"
参数类型
// 可选参数
const setInfo1 = (name: string, age?: number) => console.log(name, age)
setInfo1('Domesy') //"Domesy", undefined
setInfo1('Domesy', 7) //"Domesy", 7
// 默认参数
const setInfo2 = (name: string, age: number = 11) => console.log(name, age)
setInfo2('Domesy') //"Domesy", 11
setInfo2('Domesy', 7) //"Domesy", 7
// 剩余参数
const allCount = (...numbers: number[]) => console.log(`数字总和为:${numbers.reduce((val, item) => (val += item), 0)}`)
allCount(1, 2, 3) //"数字总和为:6"
在ts中,任何类型都归于any类型,所以any类型就成了顶级类型,如果不指定变量的类型,默认是any类型,不推荐使用该类型,因为这样丧失了ts的作用
let d:any; //等价于 let d
d = '1';
d = 2;
d = true;
d = [1, 2, 3];
d = {}
与any一样,都可以作为顶级类型,但是它更加严格,主要严格在于
let u:unknown;
let a: any;
u = '1'; //ok
u = 2; //ok
u = true; //ok
u = [1, 2, 3]; //ok
u = {}; //ok
let value:any = u //ok
let value1:any = a //ok
let value2:unknown = u //ok
let value3:unknown = a //ok
let value4:string = u //error 只能赋值给unknown或者any类型
let value5:string = a //ok
let value6:number = u //error 只能赋值给unknown或者any类型
let value7:number = a //ok
let value8:boolean = u //error 只能赋值给unknown或者any类型
let value9:boolean = a //ok
u.set() // error unknow不允许定义的值有任何操作
a.set() //ok
u() // error unknow不允许定义的值有任何操作
a() //ok
new u() // error unknow不允许定义的值有任何操作
new a() //ok
当一个函数,没有返回值时,TS会默认他的返回值为 void 类型
const setInfo = ():void => {} // 等价于 const setInfo = () => {}
const setInfo1 = ():void => { return '1' } // error
const setInfo2 = ():void => { return 2 } // error
const setInfo3 = ():void => { return true } // error
const setInfo4 = ():void => { return } // ok
const setInfo5 = ():void => { return undefined } //ok
表示一个函数永远不存在返回值,TS会认为类型为 never,那么与 void 相比, never应该是 void子集, 因为 void实际上的返回值为 undefined,而 never 连 undefined也不行
符合never的情况有:当抛出异常的情况和无限死循环
let error = ():never => {
// 等价约 let error = () => {}
throw new Error("error");
};
let error1 = ():never => {
while(true){}
}
字符串枚举
注意:字符串枚举要注意的是必须要有默认值,不支持反向映射
enum sex {
male = "男",
female = "女",
unknown = "未知",
// name, //这么写报错,无默认值
}
// 这么写 就不报错
enum sex {
name, //这么写不报错,有默认值 0
male = "男",
female = "女",
unknown = "未知",
}
console.log(sex)
打印结果:
{
female: "女"
male: "男"
unknown: "未知"
}
数字枚举
enum color {
black, // 默认是0
red = 10, //默认不是0 而是 10 只会对下面的值产生影响
green,
yellow,
}
console.log(color)
打印结果:
{
0: 'black'
10: 'red',
11: 'green',
12: 'yellow',
balck: 0,
red: 10,
green: 11,
yellow: 12
}
常量枚举
const enum sta {
A,
B,
C=7,
D
}
console.log(sta);
打印结果
0: "A"
1: "B"
7: "C"
8: "D"
A: 0
B: 1
C: 7
D: 8
常量枚举
enum sex {
a,
b = "ba",
c = 7,
d
}
打印结果
0: "a"
7: "c"
8: "d"
a: 0
b: "ba"
c: 7
d: 8
枚举的合并,不会覆盖 会直接合并
enum sex{
ci = "雌",
xiong = "雄",
}
enum sex {
male = "男",
female = "女",
unknown = "未知",
}
console.log(sex)
在TS中如果不设置类型,并且不进行赋值时,将会推论为any类型,如果进行赋值就会默认为类型
let a; // 推断为any
let str = '小杜杜'; // 推断为string
let num = 13; // 推断为number
let flag = false; // 推断为boolean
str = true // error Type 'boolean' is not assignable to type 'string'.(2322)
num = 'Domesy' // error
flag = 7 // error
字面量类型:在TS中,我们可以指定参数的类型是什么,目前支持字符串、数字、布尔三种类型。比如说我定义了 str 的类型是 ‘小杜杜’ 那么str的值只能是小杜杜
let str:'小杜杜'
let num: 1 | 2 | 3 = 1
let flag:true
str = '小杜杜' //ok
str = 'Donmesy' // error
num = 2 //ok
num = 7 // error
flag = true // ok
flag = false // error
将多个类型合并为一个类型,使用&符号连接,如:
type AProps = { a: string }
type BProps = { b: number }
type allProps = AProps & BProps
const Info: allProps = {
a: '小杜杜',
b: 7
}
类型断言会告诉编译器,你不用给我进行检查,相信我,他就是这个类型
//尖括号
let num:any = '小杜杜'
let res1: number = (num).length; // React中会 error
// as 语法
let str: any = 'Domesy';
let res: number = (str as string).length;
注意:尖括号语法在react中会报错,原因是与jsx语法会产生冲突,所以只能使用as语法
let name:string = 'huxngxiaoguo'
let nus:string;
console.log(name.trim())
//非空断言操作符 ! 可以消除编辑器 当nus为undefined时候报错
//使用时注意 保证nus不为undefined,否则运行时会报错
console.log(nus!.trim())
function myFunc(maybeString: string | undefined | null) {
const onlyString: string = maybeString; // Error
const ignoreUndefinedAndNull: string = maybeString!; // Ok
}
允许在实例属性和变量声明后面放置一个 ! 号,以告诉TS该属性会被明确赋值。
let num: number;
let num1!: number;
const setNumber = () => num = 7
const setNumber1 = () => num1 = 7
setNumber()
setNumber1()
console.log(num) // error
console.log(num1) // ok
in关键字
interface Info {
name: string
age: number
}
interface Info1{
name: string
flage: true
}
const setInfo = (data: Info | Info1) => {
if("age" in data){
console.log(`我的名字是:${data.name},年龄是:${data.age}`)
}
if("flage" in data){
console.log(`我的名字是:${data.name},性别是:${data.flage}`)
}
}
setInfo({name: '小杜杜', age: 7}) // "我的名字是:小杜杜,年龄是:7"
setInfo({name: '小杜杜', flage: true}) // "我的名字是:小杜杜,性别是:true"
typeof关键字
用于判断基本类型,如string | number等
const setInfo = (data: number | string | undefined) => {
if(typeof data === "string"){
console.log(`我的名字是:${data}`)
}
if(typeof data === "number"){
console.log(`我的年龄是:${data}`)
}
if(typeof data === "undefined"){
console.log(data)
}
}
setInfo('小杜杜') // "我的名字是:小杜杜"
setInfo(7) // "我的年龄是:7"
setInfo(undefined) // undefined"
interfaceof关键字
用于判断一个实例是不是构造函数,或使用类的时候
class Name {
name: string = '小杜杜'
}
class Age extends Name{
age: number = 7
}
const setInfo = (data: Name) => {
if (data instanceof Age) {
console.log(`我的年龄是${data.age}`);
} else {
console.log(`我的名字是${data.name}`);
}
}
setInfo(new Name()) // "我的名字是小杜杜"
setInfo(new Age()) // "我的年龄是7"
类型谓词(is)
function isNumber(x: any): x is number { //默认传入的是number类型
return typeof x === "number";
}
console.log(isNumber(7)) // true
console.log(isNumber('7')) //false
console.log(isNumber(true)) //false
接口可以用来描述对象,主要可以包括以下数据:可读属性、只读属性、任意属性
interface Props {
a: string;
b: number;
c: boolean;
d?: number; // 可选属性
readonly e: string; //只读属性
[f: string]: any //任意属性
}
let res: Props = {
a: '小杜杜',
b: 7,
c: true,
e: 'Domesy',
d: 1, // 有没有d都可以
h: 2 // 任意属性,之前为定义过h
}
let res.e = 'hi' // error, 原因是可读属性不允许更改
继承:与类一样,接口也存在继承属性,也是使用extends字段
interface nameProps {
name: string
}
interface Props extends nameProps{
age: number
}
const res: Props = {
name: '小杜杜',
age: 7
}
泛型是允许同一个函数接受不同类型参数的一种模版,与any相比,使用泛型来创建可服用的组件要更好,因为泛型会保留参数类型(PS:泛型是整个TS的重点,也是难点,请多多注意~)
为什么需要泛型
我们先看看一个例子:
const calcArray = (data:any):any[] => {
let list = []
for(let i = 0; i < 3; i++){
list.push(data)
}
return list
}
console.log(calcArray('d')) // ["d", "d", "d"]
const calcArray = (data:T):T[] => {
let list:T[] = []
for(let i = 0; i < 3; i++){
list.push(data)
}
return list
}
const res:string[] = calcArray('d') // ok
const res1:number[] = calcArray(7) // ok
type Props = {
name: string,
age: number
}
const res3: Props[] = calcArray({name: '小杜杜', age: 7}) //ok
经过上面的案例,我们发现传入的字符串、数字、对象,都能返回对应的类型,从而达到我们的目的,接下来我们再看看泛型语法:
function identity (value:T) : T {
return value
}
第一次看到这个我们是不是很懵,实际上这个T就是传递的类型,从上述的例子来看,这个就是,要注意一点,这个实际上是可以省略的,因为 TS 具有类型推论,可以自己推断类型
const calcArray = (name:T, age:U): {name:T, age:U} => {
const res: {name:T, age:U} = {name, age}
return res
}
const res = calcArray('小杜杜', 7)
console.log(res) // {"name": "小杜杜", "age": 7}
定义接口的时候,我们也可以使用泛型
interface A {
data: T
}
const Info: A = {data: '1'}
console.log(Info.data) // "1"