Using index signatures with methods - Typescript 3.5

后端 未结 2 2005
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-28 04:54
interface Keys {
  [key: string]: any
}

const obj: Keys = {
  trimDescription(text: string, length: number): string {
    return text.length > length ? text.substrin         


        
相关标签:
2条回答
  • 2021-01-28 05:31
    interface Keys {
        [key: string]: (text: string, length: number) => string;
    }
    
    const obj: Keys = {
        trimDescription(text: string, length: number): string {
            return text.length > length ? text.substring(0, length - 3) + '...' : text
        }
    }
    
    Object.keys(obj).forEach(key => {
        console.log(obj[key])
    })
    
    0 讨论(0)
  • 2021-01-28 05:49

    It all dependes in what you need your interface for. The usual is to represent the shape of your object with an interface and therefore explicitly type all the methods and then let the object "implement" it:

    interface Keys {
        trimDescription(text: string, length: number): string;
        makeUppercase(description: string, active: boolean): string;
    }
    
    const obj: Keys = {
        trimDescription(text, length) {
            return text.length > length ? text.substring(0, length - 3) + '...' : text;
        },
    
        makeUppercase(description, active) {
            // ...
        },
    };
    
    (Object.keys(obj) as (keyof Keys)[]).forEach(key => {
        console.log(obj[key]);
    });
    
    

    I guess an index signature is not what you want. There is no need for an index signature unless you need some kind of "bag" of properties of some type, then all your properties must conform to that signature.

    Also you can infer the type from the object you create:

    const obj = {
        trimDescription(text: string, length: number): string {
            return text.length > length ? text.substring(0, length - 3) + '...' : text;
        },
    
        makeUppercase(description: string, active: boolean): string {
            // ...
        },
    };
    
    // Inferred from the implict shape of the object
    type Keys = typeof obj;
    
    (Object.keys(obj) as (keyof Keys)[]).forEach(key => {
        console.log(obj[key]);
    });
    
    

    playground

    Maybe you should consider to use a class.

    The problem with Object.keys() is that it returns the type Array<string>, but string cannot index an object without an index signature. See here for the rationale. The type of the keys of a given object of type T is keyof T, so with (Object.keys(obj) as (keyof Keys)[]) I am telling TypeScript that "interprets" the array of keys as type Array<keyof Keys> so it can index the object, like obj[key]. The main issue is that, in some cases, an object can have other enumerable properties than those expressed in its type so in practice it could not be true that every key given by Object.keys() is of type keyof T; however, if you are sure that the object does not have other properties, like in the example where obj is created from an object literal, then the assertion is safe, but you need to express that explicitly.

    0 讨论(0)
提交回复
热议问题