本文介绍: # 约束对象– 一般使用 **[字面量]** 约束变量类型对象“`typescriptlet obj1: {}; // 约束变量类型对象let obj2: { name: string }; // 约束该变量的类型为 [有且只有 name 属性的] 对象, 且 name属性值的类型必须是 string“`- 可以直接给变量赋值,TS 会自动识别类型,并对变量进行约束“`typescriptlet obj = { width: 200 }; // 此时 ob

约束对象

let obj1: {}; // 约束该变量的类型为对象
let obj2: { name: string }; // 约束该变量的类型为 [有且只有 name 属性的] 对象, 且 name属性值的类型必须是 string
let obj = { width: 200 }; // 此时 obj 的类型被约束为 { width: number }

可选属性

let obj: { name: string; age?: number }; // age 属性可选
let obj: { name?: string };
obj = { name: 'superman' };
console.log(obj.name?.toLocaleUpperCase()); // SUPERMAN
obj = {};
console.log(obj.name?.toLocaleUpperCase()); // undefined

其他属性

type Person = {
    name: string;
    say(): string; // say 函数; 返回值的类型为 string
    [propName: string]: string | number; // 如果不确定 [其他属性] 的类型,可以约束为 any 类型
}; // 这种写法表示 name、age 属性必填, 其他属性可选
let obj: Person = { name: 'superman', age: 21, gender: 'male' };
console.log('obj', obj); // obj { name: 'superman', age: 21, gender: 'male' }
type MyArray1 = { [index: number]: string };
type MyArray2 = string[]; // MyArray1 与 MyArray2 等效

let arr1: MyArray1 = ["a", "b", "c"];
let arr2: MyArray2 = ["a", "b", "c"];

只读属性

type ReadonlyPerson = {
    readonly age: number;
};
let readonlyPerson: ReadonlyPerson = { age: 20 };
// readonlyPerson.age++; // 直接飘红
type Person = {
    readonly name: string;
    age: number;
};

type Superman = {
    readonly friend: Person;
};

let person: Person = { name: 'monster', age: 20 };
let superman: Superman = { friend: person };
console.log(superman); // { friend: { name: 'monster', age: 20 } }

superman.friend.age++;
// superman.friend.name = "superwomen"; // 直接飘红
console.log(superman); // { friend: { name: 'monster', age: 21 } }
type Person = {
    age: number;
};

type ReadonlyPerson = {
    readonly age: number;
};

let person: Person = { age: 20 };
let readonlyPerson: ReadonlyPerson = person;
console.log(readonlyPerson); // { age: 20 }

person.age++;
console.log(readonlyPerson); // { age: 21 }
type Person = {
    name: string;
    readonly [propName: string]: any;
};
let person: Person = { name: 'superman', age: 21 };
// person.age++; // 直接飘红

约束函数

let showSum: (num1: number, num2: number) => void; // 约束变量 fun 的类型为特定的函数
showSum = function (n1, n2) {
    console.log(n1 + n2);
};

num1num2形参名,可随便自定义表示 [有且只有 2 个参数]
number – 约束 [参数] 的类型为 number
void – 约束 [返回值] 的类型为 undefined

// 普通函数写法
function fun1(): void {
    // return true; // 直接飘红
}

// 函数表达式写法 (匿名函数)
let fun2 = function (): void {
    // return true; // 直接飘红
};

// 上下文函数类型定义
type VoidFun = () => void;
let fun3: VoidFun = () => true; // 返回 true
let res = fun3(); // res 被约束为 void 类型
console.log('res', res); // res true

可选参数

function formatNum(num?: number) {
    console.log(num?.toFixed());
    console.log(num?.toFixed(1));
}

formatNum(123.456); // 123    123.5
formatNum(); // undefined    undefined
  • 使用可选参数时,也可以在参数后面添加 !表示你确保该参数一定会被传入:
function showName(person?: { name: string }) {
    console.log("name", person!.name); // 表示参数 person 一定会被传入
}

showName({ name: "superman" });
showName(); // 此时 执行代码报错,因为没有传入参数 person

剩余参数

let buildName = (firstName: string, ...restOfName: string[]) =>
    // 如果不确定剩余参数的类型,可以约束为 any[] 类型
    // 此时 restOfName 会以数组的形式存储剩余的所有参数
    `${firstName}-${restOfName.join('-')}`;

console.log(buildName('Huang', 'Shi', 'Jie')); // Huang-Shi-Jie
const args = [1, 2];
const sum = (num1: number, num2: number): number => num1 + num2;
// console.log(sum(...args)); // 直接飘红
// 因为 sum接收两个参数,而 args 自动被 TS 约束为数组,数组可能不只两个元素

解决办法 ①:显式约束 args 为 [有且只有 2 个元素的数组],即 [元组] 类型
解决办法 ②:使用 as constargs 约束为当前 [字面量]

const args: [number, number] = [1, 2];
const sum = (num1: number, num2: number): number => num1 + num2;
console.log(sum(...args));
const args = [1, 2] as const;
const sum = (num1: number, num2: number): number => num1 + num2;
console.log(sum(...args));

调用签名

// 注意:类型是对象的形式
type FunType = {
    description: string; // 约束函数的 [属性]
    (someArg: number): boolean; // 调用签名 - 约束函数的 [参数] & [返回值]
}; // 注意, 这里用的是 `(XX: XXX): XXX`,不是 `[XX: XXX]: XXX`

function fun(num: number): boolean {
    return !!num;
}
fun.description = 'my function';

function showFun(fn: FunType, num: number) {
    console.log(`${fn.description} return ${fn(num)}`);
}
showFun(fun, 0); // my function return false
showFun(fun, 1); // my function return true

构造签名

// 定义一个
class Person {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
}

// 注意:类型是对象的形式
type FunType = {
    new (s: string): Person; // 构造签名 - 约束构造函数的 [参数] & [返回值]
};

function createPerson(ctor: FunType) {
    return new ctor('superman');
}

console.log(createPerson(Person)); // Person { name: 'superman' }

函数重载

// 参数类型不同
declare function fun(a: string): void;
declare function fun(a: number): void;

// 参数数量不同
declare function fun(n: number): void;
declare function fun(n: number, y: number): void;

// 参数类型的顺序不同
declare function fun(n: number, s: string): void;
declare function fun(s: string, n: number): void;
/* 声明 (重载函数) */
function add(arg1: string, arg2: string): string;
function add(arg1: number, arg2: number): number;
// 因为在下边有具体的函数实现,所以不需要添加 declare 关键字

/* 实现 (实现函数) */
function add(arg1: number | string, arg2: string | number): number | string {
    if (typeof arg1 === 'number' && typeof arg2 === 'number') {
        console.log('进行数相加');
        return arg1 + arg2;
    } else {
        console.log('进行字符串拼接');
        return (arg1 as string) + (arg2 as string);
    }
}

let addResult1 = add(10, 20); // addResult1 的类型为 number
let addResult2 = add('10', '20'); // addResult2 的类型为 string
// let addResult3 = add("10", 20); // 直接飘红,因为 [重载函数] 中没有允许这种类型的参数
/* 声明 (重载函数) */
function makeDate(timeStamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;

/* 实现 (实现函数) */
function makeDate(timeStampOrM: number, d?: number, y?: number): Date {
    if (d !== undefined && y !== undefined) {
        return new Date(y, timeStampOrM, d);
    } else {
        return new Date(timeStampOrM);
    }
}

let addResult1 = makeDate(1661044053502);
let addResult2 = makeDate(8, 31, 2000);
// let addResult3 = makeDate(8, 31); // 直接飘红,[重载函数] 中没有允许这种类型的参数
  • 在某些情况下,我们更偏向于使用联合类型 | 而不使用函数重载
/* 使用函数重载 */
function getLength(x: any[]): number;
function getLength(x: string): number;

function getLength(x: any): number {
    return x.length;
}

// let addResult1 = getLength(Math.random() < 0.5 ? "superman" : [1, 2, 3]); // 直接飘红
// 因为 "大" 类型不能赋值给 "小" 类型
// 而参数的类型 `"superman" | number[]` 比 `any[]` 和 `string` 都要 "大"
/* 使用联合类型 `|` */
function getLength(x: any[] | string): number {
    return x.length;
}

let addResult1 = getLength(Math.random() < 0.5 ? 'superman' : [1, 2, 3]); // 可以正常使用

关于对象类型的参数

interface Person {
    name: string;
    age?: number;
}

function showPerson({ name: string, age: number = 0 }: Person) {
    // 使用解构赋值接收对象参数
    // 此时,string、number 不是用于约束类型,而是属性的别名
    console.log('name', string); // name superman
    console.log('age', number); // age 0
}

showPerson({ name: 'superman' });

原文地址:https://blog.csdn.net/Superman_H/article/details/126455644

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_32290.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注