Ts是什么?
Ts:是TypeScript的简称,是一种由微软开发的自由和开源的编程语言。
ts和js之间有什么关系
- ts是js的超集,简单来说就是在js的基础上加入了类型系统,让每个参数变的有明确的意义,且带来了更加智能的提示。
- 相对于js来说,ts属于强类型语言,所以对于项目而言,会使代码规范起来,从而解决了大型项目代码的复杂性,但是浏览器是不识别ts的,所以编译的时候需要编译成js文件
ts的安装
npm install -g typescript //或 yarn global add typescript tsc -v //查看版本
讯享网
在线编译:https://www.typescriptlang.org/play
基本数据类型
- 基本类型:string、number、boolean、symbol、bigint、null、undefined
- 引用类型:array、 Tuple(元组)、 object(包含Object和{})、function
- 特殊类型:any、unknow、void、nerver、Enum(枚举)
- 其他类型:类型推理、字面量类型、交叉类型
基本类型
讯享网//字符串 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
- 注意:
- null 和 undefined 两个类型一旦赋值上,就不能在赋值给任何其他类型
- symbol是独一无二的,假设再定义一个 sym1,那么sym === sym1 为 false
引用类型
Array 两种方式
- 类型名称+[]
- Array<数据类型>
let arr1:number[] = [1,2,3] let arr2:Array<number> = [1,2,3] let arr3:Array<number> = [1,2,'3'] // 报错 <!-- 数字或者字符串类型 --> let arr4:Array<number | string> = [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
- 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
- Object(大写的O),代表所有的原始类型或非原始类型都可以进行赋值,除了null和undefined
讯享网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,一种是箭头函数
- 在书写的时候,可以写入返回值的类型,如果写入,必须要有对应类型的返回值.通常情况下是省略,因为TS的类型推断功能够正确推断出返回值类型
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"
特殊类型
any
在ts中,任何类型都归于any类型,所以any类型就成了顶级类型,如果不指定变量的类型,默认是any类型,不推荐使用该类型,因为这样丧失了ts的作用
let d:any; //等价于 let d d = '1'; d = 2; d = true; d = [1, 2, 3]; d = {}
unknow
与any一样,都可以作为顶级类型,但是它更加严格,主要严格在于
- unknow会对值进行检测,而类型any不会做检测操作,说白了,any类型可以赋值给任何类型,但unknow只能赋值给unknow类型和any类型
- unknow不允许定义的值有任何操作(如 方法,new等),但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
void
当一个函数,没有返回值时,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
never
表示一个函数永远不存在返回值,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: "未知" }
数字枚举
- 枚组的类型默认为数字类型,默认从0开始以此累加,如果有设置默认值,则只会对下面的值产生影响
- 同时支持反向映射(及从成员值到成员名的映射),但智能映射无默认值的情况,并且只能是默认值的前面
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,但这种类型不会编译成任何 JS,只会编译对应的值
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 }
TS断言和类型守卫
- 分为三种:类型断言、非空断言、确定赋值断言
类型断言
类型断言会告诉编译器,你不用给我进行检查,相信我,他就是这个类型
- 尖括号
- as:推荐
//尖括号 let num:any = '小杜杜' let res1: number = (<string>num).length; // React中会 error // as 语法 let str: any = 'Domesy'; let res: number = (str as string).length;
注意:尖括号语法在react中会报错,原因是与jsx语法会产生冲突,所以只能使用as语法
非空断言
- 在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型。
讯享网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
类型守卫
- 是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内
- 常有的类型守卫共有4种:in关键字、typeof关键字、interfaceof关键字和类型谓词(is)
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"
讯享网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"
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
接口可以用来描述对象,主要可以包括以下数据:可读属性、只读属性、任意属性
- 可读属性:当我们定义一个接口时,我们的属性可能不需要全都要,这是就需要 ? 来解决
- 只读属性:用 readonly修饰的属性为只读属性,意思是指允许定义,不允许之后进行更改
- 任意属性:这个属性极为重要,它是可以用作就算没有定义,也可以使用,比如 [data: string]: any。比如说我们对组件进行封装,而封装的那个组件并没有导出对应的类型,然而又想让他不报错,这时就可以使用任意属性
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"]
- 上述的例子我们发现,在calcArray中传任何类型的参数,返回的数组都是any类型
- 由于我们不知道传入的数据是什么,所以返回的数据也为any的数组
- 但我们现在想要的效果是:无论我们传什么类型,都能返回对应的类型,针对这种情况怎么办?所以此时泛型就登场了
泛型语法
讯享网const calcArray = <T,>(data:T):T[] => { let list:T[] = [] for(let i = 0; i < 3; i++){ list.push(data) } return list } const res:string[] = calcArray<string>('d') // ok const res1:number[] = calcArray<number>(7) // ok type Props = { name: string, age: number } const res3: Props[] = calcArray<Props>({name: '小杜杜', age: 7}) //ok
经过上面的案例,我们发现传入的字符串、数字、对象,都能返回对应的类型,从而达到我们的目的,接下来我们再看看泛型语法:
function identity <T>(value:T) : T { return value }
第一次看到这个我们是不是很懵,实际上这个T就是传递的类型,从上述的例子来看,这个就是,要注意一点,这个实际上是可以省略的,因为 TS 具有类型推论,可以自己推断类型
多类型传参
讯享网const calcArray = <T,U>(name:T, age:U): {name:T, age:U} => { const res: {name:T, age:U} = {name, age} return res } const res = calcArray<string, number>('小杜杜', 7) console.log(res) // {"name": "小杜杜", "age": 7}
泛型接口
定义接口的时候,我们也可以使用泛型
interface A<T> { data: T } const Info: A<string> = {data: '1'} console.log(Info.data) // "1"

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/35346.html