请考虑以下代码:
<script> var x = { setTimeout: setTimeout }; </script>
<script> x.setTimeout(function () { console.log(1) }); // TypeError </script>
<script> (0,x.setTimeout)(function () { console.log(2) }); // Ok </script>
使用setTimeout
其他this
,null
,undefined
和window
与
function f() { }
var x = { setTimeout };
x.setTimeout(f); // Fine for TS
(0, x.setTimeout)(f); // Left side of comma operator is unused and has no side effects.
未捕获的TypeError:非法调用
现在我在打字稿中编写类似的代码,结果非常不同:
this
还有一些问题:
0
推断类型。this
有副作用 - 它会在函数调用中更改0 as any
Solved通过0
代替this
。var wrapper = document.getElementById('wrapper')
function onScroll(element, scrolling, stopped) {
let timer = null
// bind the event to the provided element
element.addEventListener('scroll', function (e) {
// use a class to switch the box-shadow on
element.classList.add('scrolling')
if (typeof scrolling === 'function') {
scrolling.apply(this, arguments)
}
// clear the existing timer
clearTimeout(timer)
// set a timer for 100 ms
timer = setTimeout(() => {
// if we get in here the page has not been scrolled for 100ms
// remove the scrolling class
element.classList.remove('scrolling')
if (typeof scrolling === 'function') {
stopped.apply(this, arguments)
}
}, 100)
})
}
// call the function
onScroll(wrapper,
function scrolling(e) {
e.target.classList.add('scrolling')
},
function stopped(e) {
e.target.classList.remove('scrolling')
}
)
,但是没有一种方法可以同时使第一次调用无效,第二次有效(或者只有副作用的错误)。是否可以声明函数签名,以便只能使用全局或无效上下文执行?
答案 0 :(得分:1)
您可以使用setTimeout
参数重新声明this
签名:
declare function setTimeout(this: Window | void, handler: (...args: any[]) => void, timeout: number): number;
declare function setTimeout(this: Window | void, handler: any, timeout?: any, ...args: any[]): number;
var x = { setTimeout: setTimeout };
x.setTimeout(function () { console.log(1) }); // error: x is not window
setTimeout(function () { console.log(1) }); // ok
答案 1 :(得分:0)
Typescript是一种可以转换为javascript的打字语言。
通常,Typescript不使用输入来驱动javascript生成。
需要类型信息以确保调用者和被调用者之间的契约得到满足:当类型检查器验证所有约束都已满足时,编译器输出不再包含类型信息,而是包含普通的javascript。
表示不可能用相同的代码获得不同的结果。
要看到这一点,将noEmitOnError
compilerOption设置为false
并检查生成的javascript代码会有所帮助:已编译的代码等同于本机javascript。
回答你的问题:
TS推断类型有奇怪的。
TS确实推断this
是x
,这很好。
0有副作用 - 它在函数调用中改变了它
你是对的,但使用这个结构似乎不是惯用的,请参阅@jcalz评论和here
我已经尝试了几种方法来明确声明这一点,但是没有一种方法同时使第一次调用无效且第二次有效(或者甚至只有副作用的错误)
由于上面的序言中所说的原因,键入它不是解决问题的工具,因为您可以看到所有试验产生相同的输出。
是否可以声明函数签名,以便只能使用全局或无效上下文执行?如何在不使用call,apply和temporery变量的情况下以这种方式调用它?
不确定理解这个问题。我会说你可以用打字稿声明任何东西。如果你撒谎,编译器将不会产生错误,但运行时将失败。