在学习 TS 的过程中,你遇到过类似的错误么?
let user = {}
user.id = "TS001" // 类型“{}”上不存在属性“id”。
user.name = "阿宝哥" // 类型“{}”上不存在属性“name”。
除了 any “大招” 之外,你还知道几种解决方案?阅读完本文,你将会找到一些答案。
这是小王他的月薪是包含了基本工资和月度奖金,这是小郭他的月薪只包含合同工资。
const Wang = {
baseSalary: 10000, // 基本工资
monthlyBonus: 2000 // 月度奖金
};
const Guo = {
contractSalary: 15000 // 合同工资
}
这里我们可以实现一个 calculateSalary 函数来计算他们的薪资,计算逻辑实现起来很简单。但问题来了,在 TS 中如何定义该函数参数的类型呢?
function calculateSalary(salaryObject: ???) {
let total = 0;
for (const name in salaryObject) {
total += salaryObject[name];
}
return total;
}
给你 3 秒钟的时间思考一下。你想到答案了么?其中一种方案是使用索引签名。当我们仅知道对象键和值的类型时,就可以使用索引签名来定义该对象的类型。
这是索引签名的语法:
{ [key: KeyType]: ValueType }
其中 Key 的类型,只能是 string,number,symbol 或模版字面量类型,而值的类型可以是任意类型。
interface Dictionary {
[key: boolean]: string;
}
其中模版字面量类型是 TypeScript 4.1 版本引入的新类型,结合索引签名我们可以定义更强大的类型:
interface PropChangeHandler {
[key: `${string}Changed`]: () => void;
}
let handlers: PropChangeHandler = {
idChanged: () => {}, // Ok
nameChanged: () => {}, // Ok
ageChange: () => {} // Error
};
了解索引签名的语法之后,我们就可以轻松地定义出 salaryObject 参数的类型:
function calculateSalary(salaryObject: { [key: string]: number }) {
let total = 0;
for (const name in salaryObject) {
total += salaryObject[name];
}
return total;
}
有些时候,在定义对象类型时,会含有一些已知和未知的键,这时我们可以结合索引签名来定义该对象的类型:
interface Options {
[key: string]: string | number | boolean;
timeout: number; // 已知的键
}
const options: Options = {
timeout: 1000,
errorMessage: 'The request timed out!',
isSuccess: false
};
在使用索引签名时,你可能会遇到这些困惑:
interface NumbersNames {
[key: string]: string
}
const names: NumbersNames = {
'1': 'one',
'2': 'two',
'3': 'three'
};
const value1 = names['1'] // Ok
const value2 = names[1] // Ok
type N0 = keyof NumbersNames // string | number
这是因为当用作属性访问器中的键时,JavaScript 会隐式地将数字强制转换为字符串,TypeScript 也会执行这种转换。
除了使用索引签名之外,我们还可以使用 TS 内置的工具类型 Record 类型来定义 calculateSalary 函数的参数类型:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
function calculateSalary(salaryObject: Record<string, number>) {
let total = 0;
for (const name in salaryObject) {
total += salaryObject[name];
}
return total;
}
那么索引签名和 Record 工具类型有什么区别呢?在一些场合下,它们都能定义出期望的类型。
const user1: Record<string, string> = { name: "阿宝哥" }; // Ok
const user2: { [key: string]: string } = { name: "阿宝哥" }; // Ok
对于索引签名来说,其键的类型,只能是 string,number,symbol 或模版字面量类型。而 Record 工具类型,键的类型可以是字面量类型或字面量类型组成的联合类型:
type User1 = {
[key: "id"]: string; // Error
};
type User2 = {
[key: "id" | "name"]: string; // Error
};
type User3 = Record<"id", string>; // Ok
type User4 = Record<"id" | "name", string>; // Ok
const user: User4 = {
id: "TS001",
name: "阿宝哥",
};
看完以上内容,你学会索引签名和 Record 工具类型了么?
来源: 全栈修仙之路
在JavaScript中存在这样两种原始类型:Null与Undefined。这两种类型常常会使JavaScript的开发人员产生疑惑,在什么时候是Null,什么时候又是Undefined?Undefined类型只有一个值,即undefined。当声明的变量还未被初始化时,变量的默认值为undefined。
主要介绍了JS中检测数据类型的几种方式,typeof运算符用于判断对象的类型,但是对于一些创建的对象,它们都会返回\'object\',有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到instanceof运算符
对于object和number、string、boolean之间的转换关系,ToPrimitive是指转换为js内部的原始值,如果是非原始值则转为原始值,调用valueOf()和toString()来实现。
Undefined类型表示未定义,它的类型只有一个值为undefined。undefined和null有一定的表意差别。非整数的Number类型无法使用 == 或 === 来比较,因为 JS 是弱类型语言,所以类型转换发生非常频繁
近在做项目代码重构,其中有一个要求是为代码添加智能提示和类型检查。智能提示,英文为 IntelliSense,能为开发者提供代码智能补全、悬浮提示、跳转定义等功能,帮助其正确并且快速完成编码。
基本类型:按值访问,可以操作保存在变量中实际的值;引用类型数据存在堆内存,而引用存在栈区,也就是说引用类型同时保存在栈区和堆区,关于==的执行机制,ECMASript有规范,因为==前后的值交换顺序,返回的值也是一样的,所以在此对规范做出如下总结
JavaScript 是一种弱类型或者说动态类型语言。所以你不用提前声明变量的类型,在程序运行时,类型会被自动确定,你也可以使用同一个变量保存不同类型的数据。
js的值传递和引用(地址)传递:js的5种基本数据类型 number,string,null,undefined,boolean 在赋值传递时是值传递,js的引用数据类型(object,array,function)进行引用传递,其实底层都是对象。
JS中所有的值都可以转换成布尔类型 使用Boolean()或者 !!(两个感叹号),JS中所有的值都可以转换成数字类型,使用Number()或+。数字类型转换场景目的只有一个,用于计算,将后台传递的数据,从字符串转换为数字并参与计算
众所周知,JS在很多情况下会进行强制类型转换,其中,最常见两种是:1.使用非严格相等进行比较,对==左边的值进行类型转换2.在if判断时,括号内的值进行类型转换,转化为布尔值
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!