填上一篇文章所提到的函数公式双重协变坑
函数公式究竟是不是双重协变的?
假如你回答道打开 strictFunctionTypes
并不是,不打开便是。可以看下题
// 假定打开了 strictFunctionTypes
interface Person {
name: string;
age: number;
}
// Student 是 Person 的子类型
interface Student extends Person {
getStatus(): string;
}
interface Worker extends Person {
coding: boolean;
}
// 留意 method 用这种方法的概念方法
interface Test<T> {
method(a: T): number;
}
declare let studentTest: Test<Student>;
declare let personTest: Test<Person>;
// 不容易出错,strictFunctionTypes 并没有起效
personTest = studentTest; // Ok
studentTest = personTest; // Ok
// ⚠️ 假如我们改下 Test 中 method 的概念方法
// 留意 method 用这种方法的概念方法
interface Test<T> {
method: (a: T) => number;
}
// 此次达到预期的效果
personTest = studentTest; // error
studentTest = personTest; // ok
注重总结一下:函数公式做为目标里的属性情况下,他界定不同。实际效果完全不一样
函数公式方式
不会受到 strictFunctionTypes 设定的危害,持续保持双重协变。
interface Test<T> {
// 这类叫函数公式方式
method(a: T): number;
}
函数公式特性
interface Test<T> {
// 这类叫函数公式方式
method(a: T): number;
}
受 strictFunctionTypes 设定的危害,为true乃是逆变电源,不然双重协变。
为何
只要我们把ts编译成js,大家就懂了。
class Test {
method() {
// 这也是函数公式方式
}
property = () => {
// 这也是函数公式特性
}
}
// 编译程序后
var Test = /** @class */ (function () {
function Test() {
var _this = this;
this.property = function () {
// 这也是函数公式特性
};
}
Test.prototype.method = function () {
// 这也是函数公式方式
};
return Test;
}());
method
被写进了原型对象上,对象的常用办法也写在了原形里的。
记得以前文中,大家提及为了兼容 Array
这样的数据构造,才会导致函数公式最初被设计为双重协变吗?
这也是为什么函数公式方式也只能是 双重协变
。因此极力推荐应用 函数公式特性
!
双重协变难以保证类型安全,因此使用 双重协变 的算法设计一定要小心!
官方说法
// 危险的实例
const students: Student[] = [];
const arr: Person[] = students;
arr1.push({} as Worker);
// 欢迎来到赋值 students 自变量,别看错
// 是因为 students 取值给 arr, 而 arr 调用的 students 里的push 所导致的危险行为
students.forEach((item) => item.getStatus);
class (类)的种类该如何表明?
在ts中,class是为数不多的好多个既能当值应用,又能够当做种类所使用的算法设计。
const ImNull: null = null
const ImUndefined: undefined = undefined
class Test {
show(){}
}
// ???
const test: Test = new Test()
细心地好朋友看到了,Test 做为类名, 做为种类来使用时,表示是该类的实例。而非类自身
意思是说 const test: Test = Test
这类书写是不正确的。
正确书写是 const test: typeof Test = Test
假如我略微改一下 Test 的概念呢?
class Test {}
// 请问一下下边会不会出错
const test: Test = Test
// 回答在下文
对象
以下这些写法的意义你能够准确了解吗?
declare let fn: Function
declare let str: String
declare let obj: Object
或是下边创立吗?
fn = () => {}
fn = (...args: string[]) => {}
fn = false
fn = Boolean
fn = alert
查看答案
✅ ✅ ❌ ✅ ✅str = 'i am string'
str = String
str = Function
str = alert
查看答案
✅ ❌ ❌ ❌obj = 'i am string'
obj = Object
obj = function() {}
obj = alert
obj = false
obj = null
查看答案
✅ ✅ ✅ ✅ ✅ ❌如果你可以对了上边的所有难题,相信自己的js基本一定非常好!
最先,对象和类的概念要弄明白。实际上上面已经剧通过了,类只是一个对象的一个语法糖。所以大家可以把对象当作类来处理
那样,declare let fn: Function
的内涵便是 fn 的形式是 Function 的案例. 假如你了解 js 的原型链,上边的问题也很简单
fn = () => {} // 这也是箭头函数,因此 ok
fn = (...args: string[]) => {} // 这是也是箭头函数,因此 ok
fn = false //
fn = Boolean // Boolean 做为对象,他还是 Function 的案例。我们通过 isntanceOf 来判定
fn = alert // 内置函数,ok
如果对于原型链不太熟或是忘记了,可以参考一下之前的 文章内容
String 非常简单,也不阐述了。下边看看Object
obj = 'i am string' // 这正确,由于 String 传承 自 Object。 'i am string' 是 String 的案例
obj = Object // Object 本身就是函数公式,每一个函数公式全是 Function 的案例。 Function 又传承 Object。 因为这正确
obj = function() {} // 跟上面一样
obj = alert // 跟上面一样
obj = false // false 是 Boolean 的案例, Boolean 传承 Object。 因此恰当
obj = null // 非常明显不正确
JS圈子果真太复杂了,Function 和 Object 的私人生活太乱了
温馨提示,对象便是函数公式,基本上没有区别(除开箭头函数)。能够被 new 关键字调用的函数公式就叫做对象。
Object、object、{} 和 Record 的恩仇纠缠不清
坦白说,最初我写TS时,也总是觉得困惑。就想定一个对象,如何还有那么多的形式。但是现在基本上都是用 Record
的
Object
上面已经说过,就不多说了
object
比较特殊,他指出非原始类型。即除了 boolean、string、number、null、undefined、symbol 这种原始类型。记得 WeakMap
这一算法设计吗?
// 它键就需要:非原始类型
interface WeakMap<K extends object, V> { }
{}
这一也表示一个空对象。 相近 const obj = new Object()
这个词语。他本身没有特性,但是能够浏览 Object 里的默认方法和特性
但是自从有了 Record
之后,上边都是能够平价替代的。
object
能够写出 Record<string, unknown>
{}
能够写出 Record<string, never>
接着再提一下另一个很不好的写法,一旦发现你朋友这么写,就赶快@他来,看着我锤死他 :)
interface InputProps {
name: string
value?: string
// 这一书写是相当不太好的,就会比 any 强一点
[x: string]: any
}
完结撒花~
本站是一个以CSS、JavaScript、Vue、HTML为中心的前端开发技术网址。我们的使命是为众多前端工程师者提供全方位、全方位、好用的前端工程师专业知识和技术服务。 在网站上,大家可以学到最新前端开发技术,掌握前端工程师最新发布的趋势和良好实践。大家提供大量实例教程和实例,让大家可以快速上手前端工程师的关键技术和程序。 本站还提供了一系列好用的工具软件,帮助你更高效地开展前端工程师工作中。公司提供的一种手段和软件都要经过精心策划和改进,能够帮助你节约时间精力,提高研发效率。 此外,本站还拥有一个有活力的小区,你可以在社区里与其它前端工程师者沟通交流技术性、交流经验、处理问题。我们坚信,街道的能量能够帮助你能够更好地进步与成长。 在网站上,大家可以寻找你需要的一切前端工程师网络资源,使您成为一名更加出色的网页开发者。欢迎你添加我们的大家庭,一起探索前端工程师的无限潜能!