使用字符串访问 TypeScript 可选对象属性

发布于 2025-01-11 19:53:22 字数 1427 浏览 0 评论 0 原文

我正在现有的 JavaScript 代码库中工作。有一个类公开了预定义的函数(例如“复制”、“粘贴”)以供实用程序使用。该类可以使用“扩展”函数进行实例化,允许用户注册其他实用函数以供以后使用。

此代码未键入,因此我尝试向签名添加类型。但是我在通过名称获取实用函数的函数(get(name))方面遇到了很多麻烦。代码的最小化版本(我尝试添加类型)如下:

class Operation {
    private extensions: {[key: string]: () => void}
    constructor(extensions: {[key: string]: () => void}) {
        this.extensions = extensions;
    }
    get(name: string): () => void {
        if (this[name]) {
            return this[name].bind(this)
        }
        if (this.extensions[name]) {
            return this.extensions[name].bind(this)
        }
        // default to copy
        return this.copy.bind(this);
    }
    copy() {
        console.log('copied');
    }
    paste() {
        console.log('pasted');
    }
}
const operation = new Operation({'cut': () => { console.log('cut'); }});
operation.get('cut')();

由于 this[name] 而失败:“元素隐式具有 'any' 类型,因为类型 'Operation' 没有索引签名 ts(7053)”。

由于此函数旨在接受任意字符串(由于覆盖),因此我认为我无法避免将该函数键入为 get(name: string)。我无法从 TypeScript 文档中弄清楚如何使用 条件类型< /a>,例如 get(name: string | keyof Operation),我不相信这是正确的解决方案。

鉴于 name 不能保证是 get(name) 函数的最佳方法是什么>操作?

I'm working in an existing JavaScript codebase. There is a class which exposes pre-defined functions (e.g. "copy", "paste") for utility. The class can be instantiated with "extension" functions, which allow users to register other utility functions for later use.

This code isn't typed, so I'm trying to add types to the signatures. But I'm having a lot of trouble with the function that gets a utility function by name (get(name)). A minimised version of the code (with my attempt at adding types) is as follows:

class Operation {
    private extensions: {[key: string]: () => void}
    constructor(extensions: {[key: string]: () => void}) {
        this.extensions = extensions;
    }
    get(name: string): () => void {
        if (this[name]) {
            return this[name].bind(this)
        }
        if (this.extensions[name]) {
            return this.extensions[name].bind(this)
        }
        // default to copy
        return this.copy.bind(this);
    }
    copy() {
        console.log('copied');
    }
    paste() {
        console.log('pasted');
    }
}
const operation = new Operation({'cut': () => { console.log('cut'); }});
operation.get('cut')();

This fails because of this[name]: "Element implicitly has an 'any' type because type 'Operation' has no index signature ts(7053)".

Since this function is meant to accept arbitrary strings (because of the overrides), I don't think I can avoid typing the function as get(name: string). I couldn't figure out from the TypeScript documentation how to use conditional types, e.g. get(name: string | keyof Operation), and I'm not convinced that's the right solution.

What is the best way to (re-)structure and type the get(name) function with strict types, given that name is not guaranteed to be a property of Operation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晚风撩人 2025-01-18 19:53:22

检查(在 JavaScript 中,而不是 TypeScript)正在访问的键是否是您想要允许的直接在类上的键之一 - 例如 copypaste。然后,TS 将自动推断允许此类访问。

get(name: string): () => void {
    if (name === 'copy' || name === 'paste') {
        return this[name].bind(this)
    }
    if (this.extensions[name]) {
        return this.extensions[name].bind(this)
    }
    // default to copy
    return this.copy.bind(this);
}

Check (in JavaScript, not TypeScript) that the key being accessed is one of the ones directly on the class that you want to permit - eg copy or paste. Then, TS will automatically infer that such access is allowed.

get(name: string): () => void {
    if (name === 'copy' || name === 'paste') {
        return this[name].bind(this)
    }
    if (this.extensions[name]) {
        return this.extensions[name].bind(this)
    }
    // default to copy
    return this.copy.bind(this);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文