js是弱数据类型,ts是强数据类型,
01 函数的参数args为字符串或者字符串数组的类型
function getLen(args:string | string[]){
return args.length
}
02 自动推导与声明类型:
let a = 10; 自动推导出number类型
let b:number = 20;声明类型
03 类型的分类;
数组类型:
let arr:string[] = ['1','2','3','4']
let arr1:Array<number> = [1,2,3,4]
对象类型:
let obj:{x:number,y:number} = {
x:10,
y:20
}
type MyType = {
m:string,
n?:number
}
let obj:MyType = {
m:'hellow',
n:10
}
symbol类型:
let s1:symbol = Symbol('id')
let s2:symbol = Symbol('id')
const person = {
[s1]:'aaa',
[s2]:'ccc'
}
函数的参数类型:
function fn(x:number,y:number){
return x + y
}
函数返回值类型
function fn(x:number,y:number):number{
return x + y
}
type TodoType = {
text:string,
done:boolean
}
function fn():TodoType[]{ 返回值是上面定义的todotype的数组类型
return [{text:'今天真好',done:true}]
}
unknown类型:
function foo():string{
return 'hi ts'
}
function bar () : number{
return 123
}
let flag = true
if(flag){
res = foo()
}else{
res = bar()
}
console.log(res.length) // 这时候会报错 因为 res是unknown的类型
if(typeof res == ‘string’){ // 缩小类型
console.log(res.length) // 不会报错
}
箭头函数进行定义:fn是一个函数 这个函数没有参数没有返回值
let fn:()=> void = ()=>{} // ()=>void 这是函数的一个类型 没有形参没有返回值
type FnType = ()=> void;
let fn2:FnType = ()=>{}
never类型:在项目中基本上用不到 在封装框架的时候可能会用上
function fn():never{
throw new TypeError('抛出了一个错误')
}
function fn():never{
while(true){ // 死循环
fn()
}
}
元组类型:
let arr:[string,number,boolean] = ['a',12,true]
type MyType = [string,number,boolean] 类型别名定义元组
let arr1:MyType = ['z',12,false]
function fn(initstate:string):[string,(newValue:string)=>void]{ // 定义一个函数 返回值是元组
const initData = initstate
const setInitData (newValue:string) {
initData = newValue
}
return [initData,setInitData]
}
联合类型:
type MyType = string | number
function fn(params:myType){
if(typeof params =='string'){return params.length} // 缩小类型
return params
}
接口使用:interface, 继承使用extends 可以继承多个 中间用逗号隔开
interface InParams {
name:string,
age:number
}
function fn(params:InParams) {
return 'xxx'
}
fn({name:'zs', age:12})
interface InParams1 extends InParams {
sex:string
}
function fn(params:InParams1){
return 'xxx'
}
fn({name:'zs',age:12,sex:'男'})
接口与类型别名的区别:
接口可以被继承,接口只能指定对象类型的约束, 泛型可以是基本类型 也可以是引用类型。
接口的类名可以被重复,类型别名不能被重复。
字面量类型:
let name:'haotaotao' = 'haotaotao'
let name:'left' | 'right' | 'top' = 'left'
type MyType = 'left' | 'right'
let a:MyType = 'left'
交叉类型:所谓交叉类型就是把多个类型组合在一起 相同的进行去重
interface ITeach {
name:string,
age:number,
}
interface Icode{
name:string,
sex:string
}
type MyType = ITeach & Icode
const obj : MyType = {
name:'zs',
age:12,
sex:'男'
}
类型断言:as 主要用作于HTML元素
let img = document.queryselector('#img') as HTMLImageElement
if(img !== null) {img.src = 'xxx'}
非空类型断言:!表示在使用某个数据的时候这个数据是一定存在的
interface MyType {
name:srting,
age?:number
}
const obj:MyType = {name:'zs',age:12}
console.log(obj!.age) // 代表obj里面一定有age这个属性和值
缩小类型的方法
type MyType = number | string | string[]
// typeof 缩小
functuin fn(params:MyType){
if(typeof params == 'string')
if(typeof params == 'number')
}
type Direction = 'left' | 'right' | 'top' | 'bottom'
// 使用===缩小范围
function switeh (params:Direction){
if(params==='left')
}
// 使用in来判断一个对象中是否存在某个属性
interface ISwin {
swim:()=>void
}
interfacce IRun{
run:()=>void
}
function fn(params:ISwin | IRun) {
if(swin in params){
params.swin()
}else{
params.run()
}
}
fn({swin:()=>{console.log('2')}})
定义函数的类型:
type MyType = (a:number,b:number)=>number
function fn(par:MyType):void {
}
const A = (a:1,b:2)=>{return a+b}
fn(A)
函数调用签名: 函数即是一个函数也是一个对象有自己的属性
type FnType = ()=>void
interface FnType2 { / / 函数的类型中存在 a和b的属性
a:number,
b:number,
(num:number):number // 代表函数的参数是num 返回值是number
}
const fn:FnType2 = (num:number):number=>{
return 123
}
fn.a = 12
fn.b = 13
fn(123)
定义函数的参数是一个工厂函数:
class Person{}
interface Ifacory{
new():Person
}
function factory(cls:Ifacory){
let p1 = new cls()
return p1
}
factory(Person)
关于构造函数的ts约束
class Person{ // 父类
name:srting,
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
}
let new1 = new Person('zs',12)
class Childer extends Person{ // 子类 继承 父类
sex:string
constructor(name,age,sex){
supper(name,age)
this.sex = sex
}
}
成员修饰符:public公开,private私有的只能在自己的类中访问 ,
protected受保护的私有和子类可访问 readonly只读的不允许被修改
get set 将private设置的属性 通过get 和 set 在构造函数中定义的这两个方法进行访问和修改
class Person{
private name:srting,
private age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
asyhi(){console.log(this.name)}
get name(){return this.name}
set name (newValue) {this.name=newValue}
}
let new1 = new Person('zs',12)
console.log(new1.name) // 报错 不允许在外部访问
console.log(new1.asyhi())
console.log(new1.name)
new1.name = 'ls'
简化写法:
class A {constructor(public name:srting,public age:number){}}
枚举类型:
enum Direction {
LEFT,
RIGHT
}
let a:Direction = Direction.LEFT
enum Aaa {
Top = 100
LEFT,
RIGHT
}
let x:Aaa = Aaa.Top
console.log(x) // 100
泛型的使用:
function fn<T>(arg:T):T{ / / <T>是用来接收下面传递的参数的类型
return arg
}
let res1 = fn<number>(123) // 将参数类型number传递给上面的T的类型
let res2 = fn<string>('hellow')
多个泛型的传递
function fn<T,E>(arg:T,arg1:E):void{
console.log('泛型多个参数的传递')
}
const str1 = fn<number,string>(123,'hello')
一般泛型字母的表示:
T:type(类型) k:key(键); V:value(值);E:Element(元素);O:object(对象)
泛型接口:
interface IPerson<T> {
name:T,
age:T,
score:T
}
let p1:IPerson<number> = {
name:12,
age:12,
score:13
}
类使用泛型:
class Point<T>{
x:T
y:T
constructor(x:T,y:T){
this.x = x
this.y = y
}
}
let p1 = new Point<number>(1,2)
泛型的约束:
interface ILength {
length:number
}
function fn<T extends ILength>(arg:T):T{ // 约束T的类型需要有length的这个属性
return arg
}
fn<string>('123')
fn([1,2,3,4])
fn<number>(123) // 这个就会报错 因为number里面没有length的这个属性的
keyof的约束:相当于 定义一个对象 通过keyof 对象 能得对象中的所有的key
extends keyof O 的意思就是约束K需要是O的属性,
function fn<O,K extends keyof O>(obj:O,key:K) {
return obj[key]
}
let info = {
name:'wc',
age:12
}
console.log(fn(info,'name'))
类型的分类:
内置声明的类型:
let d:Document;
let p = new Promise(()=>{})
我们可以直接在项目中创建以.d.ts声明的ts文件,这个文件不需要导出,可以直接在ts文件中使用
第三方库对应的声明文件:axios,有些包没有第三方声明文件需要自己下载
如果在文件中加载以.svg .png等结尾的图片,ts文件会出现语法提示:
解决办法 : 在自己声明的.d.ts文件进行声明:
declare module “*.png”
declare module “*.svg”
declare module “*.jpeg”
declare module “*.jpg”
vue3使用ts:
const count = ref<number>(0)
type ToDoItem = {
id:number;
name:string;
done:boolean;
}
const list = ref<ToDoItem[]>([ ])