打字稿:传递类函数时如何检查它们是不是绑定

Posted

技术标签:

【中文标题】打字稿:传递类函数时如何检查它们是不是绑定【英文标题】:Typescript: how to check class functions are bound when passing them around打字稿:传递类函数时如何检查它们是否绑定 【发布时间】:2021-01-31 22:16:22 【问题描述】:

我是一个打字稿新手,我刚刚从docs 中了解--noImplicitThis 编译标志,但我遇到了一个看起来不像我期望的那样表现的案例,可以有人请帮助解释我如何正确键入检查绑定函数:

所以使用与文档类似的示例;尽管执行正确,但以下代码给我一个类型错误(如果跳过类型检查):

type Card = 
    suit: string;
    card: number;


class Deck 
    suits: string[];
    cards: number[];

    constructor() 
        this.suits = ["hearts", "spades", "clubs", "diamonds"];
        this.cards = Array(52);
    

    cardPicker(this: Deck): Card 
        const pickedCard: number = Math.floor(Math.random() * 52);
        const pickedSuit: number = Math.floor(pickedCard / 13);

        return  suit: this.suits[pickedSuit], card: pickedCard % 13 ;
    


// this could be a function that takes a callback as an
// argument, i.e. onClick
function runner(f: (this: Deck) => Card) : Card 
    return f();


const deck: Deck = new Deck()
const pickedCard: Card = runner(deck.cardPicker.bind(deck));
console.log("card: " + pickedCard.card + " of " + pickedCard.suit);

我有两个相关的问题:

首先,使用上面的代码:

我在 runner 函数中的 f() 上收到类型错误,尽管该函数的 this 已正确绑定:

The 'this' context of type 'void' is not assignable to method's 'this' of type 'Deck'


其次,为了使代码通过类型检查,我可以通过将runner 函数更改为:

function runner(f: () => Card) : Card 
    return f();

但是如果我(不小心)取消绑定传递给runner的函数:

const pickedCard: Card = runner(deck.cardPicker);

我没有收到编译错误,当我真的想要一个时,因为代码现在无法正确执行。


打字稿有没有办法确保在传递类函数之前绑定它们?

【问题讨论】:

【参考方案1】:

如果要捕获范围,可以使用箭头函数(包括this):

public cardPicker = () => 
    const pickedCard: number = Math.floor(Math.random() * 52);
    const pickedSuit: number = Math.floor(pickedCard / 13);

    return  suit: this.suits[pickedSuit], card: pickedCard % 13 ;

[...]
const pickedCard: Card = runner(deck.cardPicker);

Playground link with the full code

说到架构,我觉得cardPicker可以是一个以deck作为参数的外部函数,这样更容易测试。

第一个提示:避免使用幻数。

第二个提示:看看template literals,你就能写:`card: $pickedCard.card of $pickedCard.suit`

【讨论】:

谢谢 我没有考虑使用箭头函数而不是类方法。我不太确定这样做的其他含义是什么。我知道该函数随后成为一个属性,这意味着函数不会出现在类原型中,这似乎使模拟变得更加困难:medium.com/@charpeni/… 是的,这就是我添加那部分的原因I think cardPicker could be an external function taking a deck as an argument, it will be easier to test

以上是关于打字稿:传递类函数时如何检查它们是不是绑定的主要内容,如果未能解决你的问题,请参考以下文章

在 Angular 1.5 中绑定组件函数时如何利用打字稿?

为啥打字稿在实现抽象函数时忽略严格的空检查?

如何在打字稿中使用 singleton() 在构造函数中传递值?

如何在打字稿中声明函数类型

date.getDate 不是函数打字稿

绑定和返回函数中的“this”上下文中的打字稿错误