请教在typescript中动态添加元素的问题?

代码如下:

type InitPropsType<T> = {
    type: 'load'|'save';
    data: T;
};

type ActionType = {
    load: <T>(data: T) => Promise<T>;
    save: <T>(data: T) => T;
}

const action: ActionType = {
    async load (data) {
        return data;
    },
    save (data) {
        return data;
    }
}

function StorageMethod <T = any> (init: InitPropsType<T>): Promise<T>|T {
    const { type, data } = init;
    return action[type](data);
}

StorageMethod.reload = () => {};
['refresh', 'clear'].forEach(method => {
    StorageMethod[method] = () => {};
});

错误在最后StorageMethod[method],提示如下:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof StorageMethod'.
No index signature with a parameter of type 'string' was found on type 'typeof StorageMethod'.

补充说明

  • StorageMethod接收任何类型的数据,所以泛型用了<T = any>
  • 如果指定元素名称,是没有错误的,如StorageMethod.reload = () => {};
  • 如果是动态元素名称,则报错,如:StorageMethod[method]

请问如何修改使其StorageMethod[method]成立?

阅读 2k
4 个回答
interface StorageMethod {
  <T>(init: InitPropsType<T>): Promise<T> | T
  reload: () => void
  refresh: () => void
  clear: () => void
}

const storageMethod = <StorageMethod>(<T>(init: InitPropsType<T>) => {
  const { type, data } = init
  return action[type](data)
})

;(['refresh', 'clear', 'reload'] as const).forEach((m) => {
  storageMethod[m] = () => {}
})

那你可以把函数的类型定义单独抽出来

interface IStorageMethod {
    <T = any>(init: InitPropsType<T>): Promise<T>|T;
    [key: string]: any;
}

const StorageMethod: IStorageMethod = (init) => {
    const { type, data } = init;
    return action[type](data);
}

这样你赋值StorageMethod的属性的时候不会报错了,但是因为我定义的是索引类型,所以当你StorageMethod.是没有属性提示的,如果你是确定的一些静态方法只是延迟赋值,最好是具体写出类型定义而不是[key: string]: any

给函数增加属性常用于构造函数,所以你应该这么写

['refresh', 'clear'].forEach(method => {
    StorageMethod.prototype[method] = () => {};
});

为了这个定义一大堆不划算,忽略了吧,tsconfig根节点:

"ignoreDeprecations":{
    "suppressImplicitAnyIndexErrors": true,
  },

根据ts版本,有的配置是

"compilerOptions": {  
  "suppressImplicitAnyIndexErrors": true  
} 
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
Microsoft
子站问答
访问
宣传栏