TypeScript的基本语法
1. ts中let和const
//根据赋值来指导 是什么类型 之后的类型将不能改变
let str = "3";
// str = 2; // 报错,因为在声明变量的时候 类型已经被定义成了string 现在修改为number
const num = 1; // 类型为number 不能被修改 因为const为常量
// ts中,let和const的区别:let的类型由它定义的值的类型来确定,而const的类型就是它值的类型
2. ts的基本数据类型
ts的原始类型 => number string boolean undefined null symbol
// ts的原始类型 => number string boolean undefined null symbol
// 定义一个类型 冒号后面为定义的类型 之后只能赋值为这个类型
let str2:string = "1"; //定义为字符串
let bool:boolean = true; //定义为布尔
let num3:number = 10; //数字
let und:undefined = undefined;
let nul:null = null;
let sy:symbol = Symbol('123');
// Symbol创建出来的地址永远是新的(会创建新的内存空间)
// 例如:a = 123 b = 123,那么a的地址 = b的地址,而Symbol(123) != a
let vo:void = undefined; // void:空,js没有该类型
// void一般用于函数 函数(): 后面的冒号 代表着返回类型 没有返回值为void
function fn():void {
}
// 函数类型是undefined会报错,除非函数返回undefined
function fn1():undefined {
return undefined
}
3. ts的引用数据类型
// ts引用数据类型 object(常用) Object {}
let obj:object = {a: 1};
let arr:object = [1,2,3];
// let num:object = 20; // 报错,object不包含number类型
let obj1:Object = {b: 1};
let arr1:Object = [1,2,3];
let num:Object = 2; // 不会报错,Object包含
let str:Object = 'hello';
let bool:Object = true;
let obj2:{} = {b: 1};
let arr2:{} = [1,2,3];
let num2:{} = 2;
let str2:{} = 'hello';
let bool2:{} = true;
// {} 等效于 Object
4. 数组类型
// let arr:object = [1,2,3];
// 数组的元素一般数据类型都一致,便于处理
// 第一种写法:
let arr1:number[] = [1,2,3]; // 表示该数组中的【元素】的数据类型为number
arr1[0] = 10;
// arr1[1] = "10"; // 报错
// 第二种写法:泛型 类型参数化
let arr2:Array<number> = [10, 20, 30]
arr2[0] = 10;
// arr2[1] = "10"; // 报错
// 元组(不同类型的数组)
let arr3:[number, number, boolean] = [10, 20, true]
arr3[0] = 20
// arr3[1] = '123' // 报错
arr3[2] = false
5.类型或者
// |代表或
let numAndStr:number|string = 10; //可以为number类型 或者string类型
numAndStr = 'hello'; //不会报错
// 1|'2' 在这里的1 和 '2‘是类型, 常量,表示numAndStr2的值只能是 1 或 '2'
let numAndStr2: 1|'2' = 1
let numAndStr3: 1|'2' = '2'
// let numAndStr4: 1|'2' = 2 // 报错,只能是1 或 '2'中的一个
// 表明obj必须要有a 或 b属性,并且a的类型为1,或b的类型为'3'(可以a、b都有)
let obj:{a:1}|{b:'3'} = {a: 1};
// let obj:{a:1}|{b:'3'} = {a: 3}; // 报错
// let obj2:{a:1}|{b:'3'} = {a: '2'}; // 报错
let obj3:{a:1}|{b:'3'} = {b: '3'};
// let obj4:{a:1}|{b:'3'} = {b: 2}; // 报错
// let obj4:{a:1}|{b:'3'} = {b: '5'}; // 报错
6.&并且
// 并且 &
let a:number&string; // 不会有任何值满足这个类型(又是数字,又是字符串)❌
let obj:{name: string, age:number} & {height: number};
obj = {name: 'xiaotian', age: 19, height: 20} // 属性必须全部要有,少了一个都报错
// 如果一个属性出现多次类型的设置,必须都要满足才行
let obj1:{name: string, age:number} & {height: number, age: 18};
// obj1 = {name: 'xiaotian', age: 19, height: 20} // 报错, age不满足18
obj1 = {name: 'xiaotian', age: 18, height: 20}
7. any和unknown的区别
// any:不推荐使用any
let a:any = 1; // 不会去校验类型,和js没区别了
a = '123'
a = [1,2,3]
a.toFixed(2) // 绕过类型检测
// unknown:不知道什么类型
let n:unknown;
n = 1;
n = '123';
// n.toFixed(2) // 报错,有做类型检测,除非把unknown换成number
8. 接口类型interface
// interface 相当于自定义类型
// 定义接口类型 ==> 给对象用的
interface MyItf {
// 属性名: 值的类型
name: string; // 必须是分号;
age: number;
height: number;
}
let obj:MyItf;
obj = {
name: 'xiaotian',
age: 19,
height: 180
}
// 定义接口类型 ==> 给对象用的给数组用
interface ArrItf {
// [idx:number] 下标的类型: 值的类型
[idx:number]: number | string
}
let arr:ArrItf = [1,2,3,'4','5']
// 定义接口类型 ==> 给函数用的
interface FnItf {
(p: string): void
}
let fn:FnItf = (p: string) => {}
fn('')
9. 继承接口类型
interface NameItf {
name: string
}
interface AgeItf {
age: number
}
// 接口继承格式,特点:具有父接口的属性类型
interface PersonItf extends NameItf, AgeItf {
height: number
}
let p:PersonItf;
p = {
name: 'xiaotian',
age: 19,
height: 180
}
10. 接口类型同名
接口可以同名,特点:相当于合并了所有属性类型,继承一样的效果
interface AItf {
a: string;
}
interface AItf {
b: number;
}
let obj:AItf = {
// 只写一个属性会报错
a: 'hhh',
b: 1
}
11. 省略不写
interface ObjItf {
name: string;
age?: number; // 冒号前面加上问号,表示该属性可以省略不写
}
let obj:ObjItf = {
name: 'xiaotian'
}
12. 只读
interface ObjItf {
readonly name: string; // 只读 readonly
age: number;
}
let obj:ObjItf = {
name: 'xiaotian',
age: 19
}
obj.name = 'hhh' // 报错,a属性只可读
13. 或者并且类型
// & 优先于 |
let obj: {name: string} | {age: number} & {name: number} | {age: string}
obj = {
name: 'xiaotian',
age: 19
// 或
// name: 123,
// age: '19'
}
14. 类型别名
// type为自定义类型
type StringOrNumber = string | number
let str:StringOrNumber = 1;
str = "123";
type ObjType = {a:number&2, b: string}
// type ObjType = {c:string} // 报错,不能重复定义变量名
let obj:ObjType = {
a: 2, // 数字类型,并且要为2
b: 'xiaotian'
}
interface和type的区别:
interface(接口类型) 和 type(类型别名) 的区别:
可以用来自定义类型,类型别名(type)不支持重复定义,接口类型可以
interface和type结合使用:
// interface可以和type结合使用
interface AItf {
a: string
}
// 用类型别名保存接口上的某个属性类型
type Atype = AItf['a'] // Atype拿到的是一个string
let str2:Atype = '10'
15. ts函数
// 1、基础数据类型 ():冒号后面类型为返回值类型
function fn(a:number, b:number):number {
return a + b
}
// 2、接口定义函数类型
interface FnItf {
(p: string): number
}
let fn1:FnItf = (p: string) => {
return 1
}
fn1('123')
// 3、类型别名定义函数类型
type FnType = (p:string) => void
let fn2:FnType = (p: string) => {}
fn2('123')
// 4、函数作为对象的属性(接口类型)
// 写法1:
interface FnItf {
(p: string): number
}
interface ObjItf {
fn: FnItf
}
// 写法2:
interface ObjItf {
fn: (p: string) => number
}
let obj:ObjItf = {
fn: (str) => {
return 1
}
}
obj.fn('123')
// 5、类型别名定义函数类型(类型别名)
type ObjType = {fn: (p:string) => number}
let obj:ObjType = {
fn: (str) => {
return 1
}
}
obj.fn('123')
16. ts函数参数的写法
function fn(a:number, b:number) {
return a + b
}
fn(1, 2)
// fn(1) // 报错,因为第二个参数未给
// 默认参数
function fn(a:number, b:number = 2) {
return a + b
}
fn(1, 2)
fn(1)
// 缺省参数
function fn1(a:number, b?:number) {
return 1
}
fn1(1, 2)
fn1(1)
// 剩余参数
function fn2(a:number, b:number, ...arr:number[]) {
return 1
}
fn2(1, 2, 3, 4, 5)
17. ts中的Promise
interface ResItf {
code: number;
data: { a: number, b: number }[]; // 写法1
message: string;
}
let p:Promise<ResItf> = new Promise((resolve, reject) => {
resolve({
code: 0,
data: [{ a: 1, b: 2 }, { a: 11, b: 22 }],
message: ''
})
})
p.then(res => {
if (res.code === 0) {
res.data.map(item => item.a)
}
})
18. this的指向问题
18.1 未加export{}
// 在全局上,给Window接口扩展这个属性
interface Window {
myname: string
}
// ts提供Window类型,window就是Window类型的对象
function Person(this:Window, name:string) {
// 在ts的书写中,需要指明this的指向,在函数第一个形参的位置注明
// Window类型中没有myname这个属性,需要自己扩展该属性(利用接口可以同名)
this.myname = name
}
window.Person('')
18.2 加了export{}
// 在普通ts文件中
export {}
// 加了export{}, 这里就不是全局,在该文件中扩展的Window接口就失效了,需要写到 global.d.ts 中
function Person(this:Window, name:string) {
this.myname = name
}
// 这里不是全局的,Person不是window下的属性,我们需要赋值到window.Person上
window.Person = Person
window.Person('')
// 在 global.d.ts 文件中
// 在全局上给Window接口扩展这个属性
interface Window {
Person: (n:string) => void;
myname: string;
}
19. 让this指向自定义对象
export {}
type ObjType = {
myname:string;
Person: (n:string) => void;
}
let obj:ObjType = {
myname: 'xiaotian',
Person: () => {}
}
// 定义函数的时候,this的类型,必须要和调用的时候的类型一致
//Person 的函数,它使用了 this 参数的显式类型注解 this: ObjType。这意味着这个函数只能在 ObjType 类型的对象上被调用。函数内部将 this.myname 设置为传入的 name 参数。
function Person(this: ObjType, name:string) {
this.myname = name
}
obj.Person = (name: string) => Person.call(obj, name);
obj.Person('hhh')
20. this指向的联合类型的写法(18和19的联合使用)
// this: Window|ObjType
function Person(this: Window|ObjType, name:string) {
this.myname = name
}
obj.Person = Person
obj.Person('hhh')
// 必须要在 global.d.ts 中扩展了该属性
window.Person = Person
window.Person('')
21. 枚举
// 枚举不是类型,不是用来定义数据类型的,用来列举数据用的
// 写法:
enum Xxx {
a = 1, // 逗号
b = '123',
}
enum StatusCode {
success = 200,
error = 404
}
let code:string|number = 200;
if (code === StatusCode.success) {
console.log('成功');
} else if (code === StatusCode.error) {
console.log('服务器错误');
}
22. 泛型
1. 泛型的基本写法
// 泛型:指的是类型参数化,即将原来某种具体的类型参数化
// 如果参数不确定,string|number用 | 会让代码变得不利于观看
function fn(n:string|number):string|number {
return n
}
fn('123')
fn(1)
// 基本写法
// 泛型可以理解为类型的形参,T是一个自定义标识符,表示某种类型
// 单个类型参数
function fn1<T>(n:T):T {
return n
}
fn1<number>(123)
fn1<boolean>(true)
fn1<'hello'>('hello')
// 多个类型参数
function fn2<T, Y>(n:T, m: Y):T {
return n
}
fn2<number, boolean>(123, true)
2. 泛型 => 类型别名写法
// 泛型 => 类型别名
type ObjType<N, G> = {
name:N;
getName:() => G
}
let obj:ObjType<string, number> = {
name: 'xiaotian',
getName() {
return 1
}
}
3. 泛型 => 接口类型写法
// 泛型 => 接口类型
interface ObjItf<N, G> {
name: N;
getName: () => G
}
let obj2:ObjItf<string, number> = {
name: 'xiaotian',
getName() {
return 1
}
}
4. 泛型约束
interface ObjItf<N extends number|string, G=number> {
name: N; // 要求:name只能为数字或字符串
getName: () => G
}
let obj3:ObjItf<string, number> = {
name: 'xiaotian',
getName() {
return 1
}
}
23. 工具类型
1. Partial
interface PerItf {
name:string;
age:number;
}
// Partial作用:把<>里面这个接口类型设置为可缺省的属性,类似于 age?:number|undefined(也可以是undefined)
let obj:Partial<PerItf> = {
name: 'xiaotian'
}
Required
interface Per2Itf {
name:string;
age:number;
height?:number;
}
// Required作用:将可缺省的全部变为不可缺省
let obj2:Required<Per2Itf> = {
name: 'xiaotian',
age: 19,
height: 180 // 不写会报错
}
25. keyof 、in 和 typeof
1. keyof
获取key值
interface Person {
name:string;
age:number;
[idx:number]:string|number; // 只看前部分 [idx:number],这样类型就可以是number了
}
// keyof后面一般跟接口,表示接口这些属性名之一(key值),实际上就是接口冒号前的部分,冒号后的类型无所谓
type PType = keyof Person // "name" | "age" 这两个常量
let p1:PType;
p1 = 'name'
p1 = 'age'
// 加了[idx:number]后:
p1 = 123
2. in
// in
type StrOrNum = string|number;
type PTypeIn = {
[k in StrOrNum]: string
}
let obj:PTypeIn = {
a: '',
10: ''
}
3. typeof
// typeof: 用来提取变量或对象的类型
// 变量类型提取
let str = '123';
type StrType = typeof str; // 提取到str的类型为string
let a:StrType = 'hhh'
// let b:StrType = 1 // 报错,只能是字符串
// 对象类型提取
let obj1 = {
name: '',
age: 19,
height: 0
}
type ObjType = typeof obj1;
let obj2:ObjType = {
name: 'xiaotian',
age: 19,
height: 180
}
一般跟接口,表示接口这些属性名之一(key值),实际上就是接口冒号前的部分,冒号后的类型无所谓
type PType = keyof Person // "name" | "age" 这两个常量
let p1:PType;
p1 = 'name'
p1 = 'age'
// 加了[idx:number]后:
p1 = 123
2. in
// in
type StrOrNum = string|number;
type PTypeIn = {
[k in StrOrNum]: string
}
let obj:PTypeIn = {
a: '',
10: ''
}
3. typeof
// typeof: 用来提取变量或对象的类型
// 变量类型提取
let str = '123';
type StrType = typeof str; // 提取到str的类型为string
let a:StrType = 'hhh'
// let b:StrType = 1 // 报错,只能是字符串
// 对象类型提取
let obj1 = {
name: '',
age: 19,
height: 0
}
type ObjType = typeof obj1;
let obj2:ObjType = {
name: 'xiaotian',
age: 19,
height: 180
}
标签:基本,TypeScript,string,age,number,语法,let,类型,name
From: https://blog.csdn.net/m0_74079648/article/details/144717553