匿名接口
// 这种方法称为匿名的形式定义
// function greet (person:{name:string , age:number}){
// return '名字'+person.name+', 年龄'+person.age;
// }
// 与上述函数功能相同
// 这是接口的方式
// interface Person {
// name: string;
// age: number;
// }
// function greet (person:Person){
// return '名字'+person.name+', 年龄'+person.age;
// }
// 同上
// 类型别名
type Person={
name:string
age:number;
}
function greet(person:Person){
return '名字'+person.name+', 年龄'+person.age;
}
属性修改器
// 定义show
type show={}
// 定义接口
interface PaintOptions{
show: show
// xy设置成可选
xpos?:number
ypos?:number
}
// function paintShape(opts:PaintOptions){
// // 这里如果要打印xy并不会报错
// console.log(opts.xpos,opts.ypos);
// }
// function paintShape(opts:PaintOptions){
// // 进行一个简单的逻辑判断 让这个xy有值
// let x=opts.xpos?opts.xpos:0
// let y=opts.ypos?opts.ypos:0
// console.log(x,y);
// }
// 在形参这里直接结构 赋予默认值 比上面的判断优雅的多
function paintShape({show , xpos=0 ,ypos= 0}:PaintOptions){
console.log(xpos,ypos);
}
const show :show = {};
paintShape({show});
paintShape({show ,xpos:10});
paintShape({show ,xpos:10,ypos:20});
属性修改器-只读属性
// interface SomeType{
// // 指读属性
// readonly prop:string
// }
// function doSomething(obj:SomeType){
// console.log(obj.prop);
// // 这里能访问但不可修改
// }
// doSomething({prop: "something"})
type shap={
name:string
age:number
}
interface SomeType{
// 指读属性
readonly prop:shap
}
function doSomething(obj:SomeType){
console.log(obj.prop);
// 这里能访问但不可修改
// 但可以修改指读属性值的值
obj.prop.name='李四'
console.log(obj.prop);
}
doSomething({prop: {name:"Joe",age:31}})
属性修改器-索引签名
interface StrinArray{
// 定义数组的index为string的接口
[ index:number]:string
}
const myArray:StrinArray=["hello","world","!"]
const myArray2=myArray[1]
// string类型
interface TestString{
// 这里对应的键定义为string类型,值定义为数值的接口
[props:string]:number
}
let testString:TestString={
// 只能写string的键 数值的值
a:100,
b:200,
aaa:123
}
interface Anima{
name :string
}
interface Dog extends Anima{
berrd:string
}
let anima:Dog={name:"Bulldog", berrd:"Fido"}
interface Notok{
[index:string]:number|string
length:number
name:string//如果这里定义number上面写上|string
}
let notOk:Notok={
x:100,
length:100,
name:'admin'
}
// 索引签名 给我们的功能 可以给任意的一个对象定义属性 这样就可以扩展对象属性的范围
// 索引签名也可以定义指读类型
interface ReadOnly{
[index:string]:number|string
// 这里定义name为只读类型不可修改
readonly name:string
age:number
}
let Msg:ReadOnly={
name:'张三',
age:12
}
// Msg.name='abc'name不能改
Msg.age=20
扩展类型
interface BasicAddress{
name?:string
street:string
city:string
country:string
postalCode:string
}
// 只多了一个 这么全部写上不优雅
// interface ADDress{
// name?:string;
// street:string;
// city:string;
// country:string;
// postalCode?:string;
// unit:string
// }
// 简洁优雅 并继承了BasicAddress的接口类型。 并扩展了unit
interface ADDress extends BasicAddress{
unit:string
}
let awu:ADDress={
street:'上海',
city:'上海',
country:'zhongguo ',
postalCode:'035790',
unit:'3'
}
interface Colorful{
color:string;
}
interface Colorful2{
radius:string;
}
interface Colorfulcircle extends Colorful,Colorful2{
}
const color:Colorfulcircle={
color:'#333',
radius:'100%',
}
交叉类型
interface colorful{
color:string
}
interface circle{
radius:number
}
// 交叉和extends差不多
type Colorfulcircle1=colorful&circle
// 里面的属性必须两个定义里面的都要存在
const clr:Colorfulcircle1={
color:'red',
radius:111
}
接口与交叉类型
interface Sisrer{
name :string
}
interface Sisrer{
age :number
}
// 这里重名定义是通过合并的方式实现
const sister:Sisrer={
name:'qwe',
age:42,
}
// 类型别名
type Sisrer1={
name: string
}
// 直接报错
// type Sisrer1={
// name: string
// }
// 总结 区别 如果是实现一些合并可以用接口interface来定义, 如果避免冲突的话就可以使用type类型别名的方式。
泛型对象类型
// 按照用户传入的类型识别并对应的进行功能
// interface BOX{
// conrents:any
// }
// // 使用any失去了我们对类型定义的意义
// let box :BOX={
// conrents:'hello'
// }
interface BOX{
conrents:unknown
}
let b:BOX={
conrents:'hello'
}
// console.log(b.conrents.toLowerCase);//这里不能直接用 必须要用一个类型缩小
if(typeof b.conrents==='string'){
console.log(b.conrents.toLowerCase)
}
// 还可以直接断言为一个string类型也是可以直接使用
console.log((b.conrents as string).toLocaleLowerCase);
// unknown 和 any都不是最好的 或者说也可以 只是一个特殊的类型,谁就不知道哪里获取到值了??
// 根据用户自己传入这个类型直接写死
// 利用函数的重载
interface NuberBox{
contents:number
}
interface StringBox{
contents:string
}
interface BooleanBox{
contents:boolean
}
function setContents(box: StringBox,newContents:string):void
function setContents(box: NuberBox,newContents:number):void
function setContents(box: {contents:any},newContents:any){
// 根据对象的不同类型传入,重载将对应类型解析成对应的类型的函数或类型。 书写的不优雅 不简介
box.contents=newContents
}
// 泛型对象定义
interface Box<T>{
contents:T
}
let boxa:Box<number>={
contents:100
}
//
interface BOx<T>{
contents:T
}
interface Apple{
//...
}
//这里的AppleBox相当于继承了BOx的属性并传入Apple的类型
type AppleBox=BOx<Apple>
// 定义aa为传入类型
let aa:Apple={}
// 把aa写入内部
let ab:AppleBox={
contents:aa
}
// 这个就解决了ab包扩里面所有的类型问题。 把一个泛型的类型传入函数中,就可以直接写出对应的泛型函数。
// 如果没有可用于某个类型的属性,则不会发生什么。
//类型别名来定义泛型对象类型
type Box1<T>={
contents:T
}
type Ornull<T>=T|null
type OrnullMany <T>=T|T[]
type OrnullManyNnll<T>=Ornull< OrnullMany<T>>
type OrnullManyNnllString=OrnullMany<string>
// 通用类型 多层嵌套 让每一层的数据都为可控