编辑代码

/**
 * 有时候我们希望传入的类型有某些共性,但是这些共性可能不在同一种类型中
 * 
 * 比如string和array都是有length属性的,或者某些对象也是会有length属性的
 * 那么只要是拥有length的属性都可以作为我们的参数类型,那么应该如何操作呢?
 */
interface Ilength {
    length: number
}
// 这里表示传入的类型必须有这个属性,也可以有其他属性,但是必须至少有这个成员
function getLength<T extends Ilength>(arg: T): T {
    return arg
}

let res = getLength<string>('str')
let res1 = getLength<string[]>(['1', '2', '3'])
let res2 = getLength<{
    name: string
    length: number
}>({
    name: 'str',
    length: 777
})

/**
 * 在泛型约束中使用类型参数
 * 你可以声明一个类型参数,这个类型参数被其他类型参数约束
 * 
 * 例如,我们希望获取一个对象给定属性名的值
 * 我们需要确保我们不会获取obj上不存在的属性
 */

function getProperty<T, K extends keyof T>(arg: T, key: K): T[K] {
    return arg[key]
}
interface Obj {
    name: string,
    height: string,
    age: number
}
let obj = {
    name: '张三',
    height: '180cm',
    age: 18
}
let getName = getProperty<Obj, 'name'>(obj, 'name')
let getheight = getProperty<Obj, 'height'>(obj, 'height')
let getAge = getProperty<Obj, 'age'>(obj, 'age')