TypeScript基础
数据类型
typescript会进行类型推导,不需要每个都写类型注释
数组
let list1:string[]=['aa','bb'] // 数组类型并且内容都为string
let list2:any[] = ['aa',1,3]
let list3:Array<string> = ['aa','aa2','bb']
枚举
enum Dict {
UP=1<<1, // 默认=0
Down=1<<2,
LEFT,
RIGHT='ddd'
}
const d1: Dict = Dict.UP
Object类型
type infoType = {
name:string
age:number
y // 任意类型
x?: number // 可选
}
let info:infoType = {
name:'ss',
age:33,
y:2,
}
let info2:Object = { // info2.name 报错 Object表示一个空对象
name:'ss',
age:33
}
Symbol类型
const s:symbol = Symbol('aaa')
null和undefined
let a:null = null
let b:undefined = undefined
string
let s:string = 'aaa'
函数类型
type infoType = {
name:string
age:number
}
// 剩余参数类型 (...arg:number)
function foo(name:string,...arg:number[]): infoType[] {
let info:infoType[] = []
info.push({name:'ss',age:33})
return info
}
匿名函数不需要进行类型注释,根据上下文会自动指定
any
let a:any = ''
a=3
console.log(a.length)
unknown
与any的区别:
unknown类型进行任何操作都是不合法的
any类型任何操作都是合法的
unknown类型必须进行校验
let a:unknow = ''
console.log(a.length) // 报错
// unknow类型必须进行校验, 类型缩小
if (typeof a === 'string') {
console.log(a.length)
}
void
指定一个函数没有返回值
function foo():void {
return undefined // 允许void类型返回undefined
}
type FnType = ()=>void
function foo(fn:FnType):void {
fn()
return undefined // 允许void类型返回undefined
}
// type FooType = (name:string)=>infoType[]
function foo(name:string): infoType[] {
let info:infoType[] = []
info.push({name:'ss',age:33})
return info
}
never
表示的是那些永不存在的值的类型
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
元组
已知元素数量和类型的数组,各元素的类型不必相同
数组类型应该是同一类型
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
联合类型
联合成员,二个及以上
let s:string | number = ''
交叉类型
并集
let s:IPointType & IPointType2
类型别名
type 关键字
type MyType = number | string
function printID(id:MyType){
console.log(id)
}
接口别名
interface 关键字
interface PointType {
x: number
y: number
z?:number
}
// 可以多次声明
interface PointType {
name: string
}
// 继承
interface PointType2 extends PointType{
age:number
}
function foo(point:PointType){
}
与type区别
- 在定义对象类型时,大部分情况都可使用
- type的使用范围更广,interface 只能声明对象
- interface 可以多次声明, type不允许相同的别名存在
- interface 支持继承
类型断言
const imgEl = document.querySelector('.img')
// 不确定imgEl 是什么对象时
imgEL.src // imgEl不是HTMLImageElement时报错
// 类型断言:确定类型时使用
const imgEl = document.querySelector('.img') as HTMLImageElement
as 关键字
断言规则:
- 更加具体的类型
- 不太具体类型: any 、unkown
非空类型断言:?!
info.obj?.name
info.obj!.name='xxx'
obj强制不为空,危险
字面量
const name:'hyf' | 'aa' | '3' = '3'
调用签名
函数可被调用,并且有其他属性
与 type 定义的区别: type 不包含其他属性
interface ICallBack {
name:string;
age:number;
(dir:string):string // type xxx = (dir:string)=>string
}
const callback: ICallBack = (dir:string):string=>{
return dir
}
构造签名
class Person {
}
interface Iclass {
new ():Person
}
函数的重载
// 函数重载签名
function foo(arg:number,arg2:number):number
function foo(arg:string,arg2:string):string
// 通用函数实现
function foo(arg:any,arg2:any):any{
return arg+arg2
}
this
默认是any类型
tsconfig.json
noImplicitThis: 是否允许模糊的this
内置工具
ThisParameterType
// 提取函数中this类型
type FooType = typeof foo
type FooThisType = ThisParameterType<FooType>
OmitThisParameter
过滤this
// 省略this,
type PureFooType = OmitThisParameter<FooType>
ThisType
绑定一个上下文的this
interface ISate {
name:string
}
interface IState{
state:ISate
eating:()=>void
}
// & ThisType<ISate> 绑定this 上下文
const store:IState & ThisType<ISate> {
...
eating(){
console.log(this.name)
}
}
Partial
把一个对象中类型转为可选的
interface IT{
name:string
}
//使用
type ITOption = Partial<IT> // name?:string
// 实现
type HYPartial<T> = {
[P in keyof T]?:T[P]
}
Required
把一个对象中类型转为必选的
interface IT{
name?:string,
age:number
}
//使用
type ITOption = Required<IT> // name:string;age:number
// 实现
type HYRequired<T> = {
[P in keyof T]-?:T[P]
}
Readonly
把一个对象中类型转为只读的
interface IT{
name?:string,
age:number
}
//使用
type ITOption = Readonly<IT> // readonly name:string; readonly age:number
// 实现
type HYReadonly<T> = {
readonly [P in keyof T]:T[P]
}
Record<keyType,valueType>
interface IT{
name?:string,
age:number
}
type t1 = 'aaa'|'ddd'|'ccc'
//使用
type ITOption = Record<t1,IT> // key的类型必须是t1, value的类型必须是t2
const option:ITOption = {
aaa:{
name:'xxx',
age:22
},
ddd:{
age:22
}
}
type Res = keyof any // number|string|symbol
// 实现
type HYRecord<Keys extends keyof any,T> = {
[P in keyof Keys]:T
}
- t1是一个联合类型
- 确保t1 是一个可以作为key的联合类型: <Keys extends keyof any,T>
Pick<Type,Keys>
挑选出 类型 组成新的类型
interface IT{
name?:string
age:number
height:number
}
// 选出age,height
type ITOption = Pick<IT,'height'|'age'>
// 实现
type HYPick<T,K extends keyof T> = {
[P in K]:T[P]
}
Omit<Type,Keys>
过滤属性
interface IT{
name?:string
age:number
height:number
}
// 去除age,height
type ITOption = Pick<IT,'height'|'age'> // name?:string
// 实现
type HYOmit<T,K extends keyof T> = {
// 判断P 是否存在于 K中 存在 never 否则 返回对应P(属性)
[P in keyof T as P extends K? never:P ]:T[P]
}
Exclude
在联合类型中 排除掉
type MYType = 'aaa' | 'bbb' | 'ccc'
type ITOption = Exclude<MYType,'aaa'> // 'bbb'|'ccc'
type HYExclude<T,E> = T extends E? never:T
Extract
在联合类型中提取
type MYType = 'aaa' | 'bbb' | 'ccc'
type ITOption = Extract<MYType,'aaa'|'bbb'> // 'aaa'|'bbb'
type HYExtract<T,E> = T extends E? T : never
NonNullable
排除所有null/undefined类型
type MYType = 'aaa' | 'bbb' | 'ccc' | null | undefined
type ITOption = NonNullable<MYType> // 'aaa' | 'bbb' | 'ccc'
type HYNonNullable<T> = T extends null|undefined? never :T
ReturnType
获取一个函数的返回值类型
// 获取一个函数的返回值类型
type CallFn = (arg1:number,arg2:number2) => number
function foo(){
return 'foo'
}
type CallReturnType = ReturnType<CallFn> // number
type FooReturnType = ReturnType<typeof foo> // string
type HYReturnType<T> =
// 必须是函数类型 限制类型 extends (...args:any) => any
// 第二个extends表示 T 属于 xxx类型吗?
// 加上推断infer
type HYReturnType<T extends (...args:any) => any > = T extends (...args:any) => infer R? R:never
InstanceType
所有构造函数的实例的类型
class Person1 {
constructor(){
}
}
// 区别 typeof Person 和 Person
// typeof Person 构造函数具体类型
function factory<T extends new (...arg:any[])=>any>(ctor:T):T{
return new ctor()
}
const a = factory(Person) // function factory<typeof Person>(ctor: typeof Person): typeof Person
// InstanceType 构造函数创建出来实例对象的具体类型 Person
function factory2<T extends new (...arg:any[])=>any>(ctor:T):InstanceType<T>{}
return new ctor()
}
const a1 = factory2(Person) // function factory<typeof Person>(ctor: typeof Person): Person
type HYInstanceType<T extends new (...args:any) => any > = T extends new (...args:any) => infer R? R:never
类的使用
class Person {
// 严格模式下,需要初始化,可以使用name!:string的语法不初始化,
name!: string
age: number
constructor(name:string,age:number){
this.name = name
this.age = age
}
eating(){
}
}
// 语法糖 ,同名参数可以在construct函数中 在参数前加上修饰符表示
class Person {
// name: string
// age: number
constructor(public name:string, private age:number){
this.name = name
this.age = age
}
eating(){
}
}
public
公共的,默认就是public
private
私有的, 只在类的内部访问
protected
只在类及子类中使用,受保护的属性和方法
readonly
只读属性,不能写入
getter/setter
如果有私有属性需要给到外界,可以使用getter、setter
抽象类 abstract
abstract class Person {
// 只声明没有实现体
// 不能实例化
// 抽象方法必须存在抽象类中
abstract eating()
}
class Child1 extends Person {
// 子类必须实现 eating
eating(){
console.log(1)
}
}
class Child2 extends Person {
// 子类必须实现 eating
eating(){
console.log(2)
}
}
function foo(shap:Person){
shap.eating()
}
foo(new Child1())
foo(new Child2())
索引签名
interface ICollection {
// 索引签名, length需要和 index 返回值类型一致
[index:number]:any; // 通过数字类型 arr[0]访问
[index2:string]:any; // 可以通过字符串类型 obj['name']
length:number
}
泛型
将类型当做参数传入
function foo<T>(arg:T):T{
return arg
}
const res1 = foo<number>(123)
const res2 = foo<string>('aaa')
const res3 = foo<{name:string}>({name:'sss'})
// 省略写法
const res4 = foo('aaaaa') // 会自动进行类型推理
接口泛型
interface IFoo<T = string> {
name:T;
age:number
}
const foo:IFoo<string> = {
name:'xxx',
age:22
}
const foo2:IFoo<number> = {
name:222,
age:22
}
// 默认类型 string
const foo3:IFoo = {
name:'222',
age:22
}
泛型类的使用
class Person<T = string> {
name:T
age:T
constructor(name:T,age:T) {
// ...
}
}
const person = new Person('123','123')
const person2 = new Person<number>(1,2)
泛型约束extends
不会丢失自身的类型属性 泛型参数约束
<O,T extends keyof O>
映射类型
只能使用type,不能使用interface
type MapPerson<T> = {
[property in keyof T]:T[property]
}
interface Person{
name:'sss0';
age:33
}
type PersonCopy = MapPerson<Person>
可选属性
type MapPerson<T> = {
[property in keyof T]?:T[property]
}
interface Person{
name:'sss0';
age:33
}
type PersonCopy = MapPerson<Person>
只读属性
type MapPerson<T> = {
readonly [property in keyof T]?:T[property]
}
interface Person{
name:'sss0';
age:33
}
type PersonCopy = MapPerson<Person>
+和-
默认修饰符前是+,
-?
: 去掉? 必传
type MapPerson<T> = {
+readonly [property in keyof T]-?:T[property]
}
interface Person{
name:'sss0';
age:33
}
type PersonCopy = MapPerson<Person>
模块化
js 文件如果 有export 那么就被认为是一个模块
ts中 如果导入的类型,需要在类型前加 type 关键字
import type {IPerson} from './index.ts'
命名空间
目前使用ES module
namespace xxx {
export function foo(){
console.log(3)
}
}
export {
xxx
}
.d.ts
文件
只写类型的声明,告知typescript 有哪些类型
- 内置类型声明
+- 外部定义类型声明
- 自定义类型声明
declare 类型声明
// 声明变量,可以让在ts中使用这些变量而不报错
declare const name:string
declare const age:number
// 声明函数
declare function foo(bar:string): string
// 声明类
declare class Person {
constructor(public name:string,public age:number)
}
// 声明文件模块
declare module "*.png"
declare module "*.svg"
declare module "*.jpg"
declare module "*.jpeg"
// 声明模块
declare module MyAxios {
export const method:string
}
// 命名空间 $.axios
declare namespace $ {
export function axios(config:any): any
}
tsconfig配置
创建:
tsc --init
使用:
tsc [filename] // 如果跟文件,会忽略当前的tsconfig.js的配置
配置选项:
{
"compilerOptions": {
"target": "ESNext", // 将代码编译为最新版本的 JS
"useDefineForClassFields": true, // 使用 Object.defineProperty 定义 class 中的属性,而非使用 obj.key = value 的形式定义属性
"module": "ESNext", // 使用 ES Module 格式打包编译后的文件
"moduleResolution": "Node", // 使用 Node 的模块解析策略
"strict": true, // 启用所用严格的类型检查
"jsx": "preserve", // 保留原始的 JSX 代码,不进行编译
"sourceMap": true, // 生成 sourceMap 文件
"resolveJsonModule": true, // 允许引入 JSON 文件
"isolatedModules": true, // 该属性要求所有文件都是 ES Module 模块。
"esModuleInterop": true, // 允许使用 import 引入使用 export = 导出的内容
"lib": ["ESNext", "DOM"], // 引入 ES 最新特性和 DOM 接口的类型定义
"skipLibCheck": true // 跳过对 .d.ts 文件的类型检查
},
files:[] // 指定哪些ts文件需要编译,项目较小时适合
include:[] //
exclue:[],
}
条件类型
someType extends otherType ? TrueType: falseType // 和 三元运算符类似
推断 infer
// 推断出类型,在true分支中返回
someType extends infer R ? R: never
分发类型
type toArray<T> = T extends any?T[]:never
type newType = toArray<number|string> // 如果传入的是联合类型会进行分发 string[]|number[]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析