【问题标题】:What is the proper way to type a method that receives an object and updates properties?键入接收对象并更新属性的方法的正确方法是什么?
【发布时间】:2021-04-18 18:25:53
【问题描述】:

我的问题是关于我的 update 方法。正如您在下面看到的,它可以接收一个对象(newState),并使用 Object.assign() 更新类实例属性。我需要告诉 TS 它应该只接受:

  • 一个对象
  • 作为状态类键的属性
  • 这些属性的值是属性的正确类型。

我是否正确输入了这个方法?有更好的//其他方法吗?

另外,在main.ts中,在State类实现StateInterface上,TS编译器有错误提示update(newState)的参数隐式为any。它不应该从 types.d.ts 接收类型信息吗?:

/// types.d.ts
export interface StateInterface {
    user: User;
    fileList: DirectoryResponse;
    selectedFiles: Array<SelectedFile>;
    currentDir: string;
    response: APIResponse;
    menu: Menu;
    dialog: Dialog;
    history: object;
    update: <P extends StateInterface, T extends keyof StateInterface>(newState: { [key in T]: P[T]}) =>
                                                                                            Promise<void>;
    syncPage: () => void;
}

/// main.ts
class State implements StateInterface {
    user: User;
    fileList: DirectoryResponse;
    selectedFiles: SelectedFiles;
    currentDir: string;
    response: APIResponse;
    menu: Menu;
    dialog: Dialog;
    history: History;

    constructor(user: User, fileList: DirectoryResponse, selected: SelectedFiles, currentDir: string, response: APIResponse, menu: Menu, dialog: Dialog, history: History = { forward: false, back: false }) {
        this.user = user;
        this.fileList = fileList;
        this.selectedFiles = selected.slice();
        this.currentDir = currentDir;
        this.response = response || { fileResults: [], folderResults: [] };
        this.menu = menu || { location: '', type: 'folder' };
        this.dialog = dialog || { type: "", state: false };
        this.history = history;
        }

        get dir() {
            return this.currentDir.slice(1).split('/');
        };

        async update(newState): Promise<void> {
                     ^^^^^^^^ (implicit any)
            if (newState) {
                Object.assign(this, newState);
            } 
            
            this.fileList = await readDir(this.currentDir).then(r=>r.json());
        }
}

【问题讨论】:

    标签: javascript typescript generics keyof


    【解决方案1】:

    您键入 StateInterface 的方式表明您只需要 newState 中的 StateInterface 键(而不是 State 中可能存在的其他属性)。

    如果是这种情况,我会在接口和类中都输入 update as

    update(newState: Partial<StateInterface>): void {
      ...
    }
    

    还请注意,这允许替换 StateInterface 中存在的函数,您可能想使用 Omit 删除不需要的键。

    【讨论】:

    • 是的,我只想更新 StateInterface 的键。我不希望有人在类实例上添加随机的额外密钥。我会看看省略,谢谢!
    • 请注意,这只是编译时检查,如果你的 newState 符合 Partial 但在运行时还有一些额外的属性,额外的属性将被复制(可能是也可能不是问题,取决于您的用例)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多