真实的setTimeout类型

时间:2018-01-14 00:49:33

标签: typescript

请考虑以下代码:

<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其他thisnullundefinedwindow

崩溃,致电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

还有一些问题:

  1. TS使用奇怪的0推断类型。
  2. this有副作用 - 它会在函数调用中更改0 as any Solved通过0代替this
  3. tried有几种方法可以明确声明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') } ),但是没有一种方法可以同时使第一次调用无效,第二次有效(或者只有副作用的错误)。
  4. 是否可以声明函数签名,以便只能使用全局或无效上下文执行?

2 个答案:

答案 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确实推断thisx,这很好。

  

0有副作用 - 它在函数调用中改变了它

你是对的,但使用这个结构似乎不是惯用的,请参阅@jcalz评论和here

  

我已经尝试了几种方法来明确声明这一点,但是没有一种方法同时使第一次调用无效且第二次有效(或者甚至只有副作用的错误)

由于上面的序言中所说的原因,键入它不是解决问题的工具,因为您可以看到所有试验产生相同的输出。

  

是否可以声明函数签名,以便只能使用全局或无效上下文执行?如何在不使用call,apply和temporery变量的情况下以这种方式调用它?

不确定理解这个问题。我会说你可以用打字稿声明任何东西。如果你撒谎,编译器将不会产生错误,但运行时将失败。