Home > Enterprise >  How to solve TS7053 issue in replace method?
How to solve TS7053 issue in replace method?

Time:10-18

I have a problem. I'm trying to get data to be encoded and further used when downloading. All functionality works correctly and gives what I expect. But I get a typescript error when declaring the format constant in the place where the return occurs ( under context )

Error : TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ worksheet: string; table:string; }'.

Below is the code. Table is an element from the dom tree that I find by id

  const template =
    '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic'  
    'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha'  
    'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce'  
    "lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>"  
    "</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></"  
    "xml><![endif]--></head><body>{table}</body></html>";

  const context = {
    worksheet: "tablexls",
    table,
  };

const format = template.replace(/{(\w )}/g, (m, p) => context[p]);

CodePudding user response:

The issue is that TypeScript doesn't know that p is a valid key for context. Maybe you don't know that either, because you can't be sure that all of the placeholders in the string are in fact valid keys for context; it depends on where that string comes from.

If you want to assume that it is, the fully type-safe way to do that is to have a type assertion function along these lines:

function assertsIsKeyOf<ObjectType>(object: ObjectType, key: string): asserts key is keyof ObjectType & string {
    if (!(key in object)) {
        throw new Error(`Key ${JSON.stringify(key)} expected but not found in object.`);
    }
}

Then your replace call would be:

const format = template.replace(/{(\w )}/g, (m, p: string) => {
    assertsIsKeyOf(context, p);
    return context[p];
});

But you might not want to make that assumption, in which case you might want a type predicate instead:

function isKeyOf<ObjectType>(object: ObjectType, key: string): key is keyof ObjectType & string {
    return key in object;
}

Then the call is:

const format = template.replace(/{(\w )}/g, (m, p: string) => {
    if (!isKeyOf(context, p)) {
        // Do something to handle the fact th ekey isn't valid, like throwing an error,
        // or returning a static value
        throw new Error(`Template has invalid key ${JSON.stringify(p)}`);
    }
    return context[p];
});

Playground link for all the above

  • Related