54

ERROR in ...component.ts (..,..): A computed property name in a type literal must directly refer to a built- in symbol. ...: Cannot find name 'any'.

I'm looking forward an object which contains strings which have other string, i.e:

{ abc: 'xyz' }

What I did:

foo: { [string]: string };
zurfyx
  • 31,043
  • 20
  • 111
  • 145

4 Answers4

63

An identifying name on the computed value is required:

foo: { [bar: string]: string };
zurfyx
  • 31,043
  • 20
  • 111
  • 145
  • 6
    Just a note that if your key type comes from a generic, you'll need to use a different solution: https://stackoverflow.com/a/65996861/10246801 – Eric Feb 01 '21 at 16:57
42

I had a similar issue after building. The two issues I faced were with using numbers and or enum values as keys in objects. Just to help those that see this in the future.

Enums as keys

export enum MyEnum {
  one = 'stringOne',
  two = 'stringTwo',
}

export const someMap = {
  [ MyEnum.one ]: 'valueOne',
  [ MyEnum.two ]: 'valueTwo',
};

This will transpile someMap to a type that look something like...

export declare const someMap: {
  [ MyEnum.one ]: string;
  [ MyEnum.two ]: string;
};

Note the keys are still the enum value and not strings, typescript/angular does not like that because it is expecting something like...

export declare const someMap: {
  [ x: string ]: string;
};

So two possible fixes are...

1) Assign explicit type to someMap

export interface ForceStringType {
  [product: string]: string;
}
export const someMap: ForceStringType = {
  [ MyEnum.one ]: 'valueOne',
  [ MyEnum.two ]: 'valueTwo',
};

2) Assign string type to keys of someMap

export const someMap: ForceStringType = {
  [ MyEnum.one as string ]: 'valueOne',
  [ MyEnum.two as string ]: 'valueTwo',
};

Numbers as keys

const CONSTANT_ONE = 123;
const CONSTANT_TWO = 321;

export const someMap = {
  [ CONSTANT_ONE ]: 'valueOne',
  [ CONSTANT_TWO ]: 'valueTwo',
};

This will transpile someMap to a type that look something like...

export declare const someMap: {
  [ CONSTANT_ONE ]: string;
  [ CONSTANT_TWO ]: string;
};

Note the keys are still the constant/number value and not strings, typescript/angular is again expecting something like...

export declare const someMap: {
  [ x: string ]: string;
};

So one possible fix is...

Interpolate number as string for each key of someMap

export declare const someMap: {
  [ `${CONSTANT_ONE}` ]: string;
  [ `${CONSTANT_TWO}` ]: string;
};

Note: Accessing a value from someMap with the constant/number as a key should not matter as typescript will coerce it to a string anyway, but probably best for overall consistency.

const valueOne: string = someMap[ CONSTANT_ONE ];
// vs
const valueOne: string = someMap[ `${CONSTANT_ONE}` ];
Nickofthyme
  • 3,032
  • 23
  • 40
31

The currently accepted answer will not work if the key type comes from a generic. For that to work, you need to use the in operator:

type WithKey<K extends string | number | symbol> = {
    [k in K]: boolean
}

Credit here.

Eric
  • 741
  • 6
  • 10
1

I was having this issue in a Vue component, my problem was that I was incorrectly binding class names:

Vue documentation

<script lang="ts">
import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  props: {
    className: String,
  },

  setup() {
    const isModified = computed<boolean>(() => true)

    return {
      isModified,
    }

<template>
  <!-- BAD -->
  <div 
    class="static-class" 
    :class="{ [className]: true, 'static-class--modified': isModified }]">
  </div>

  <!-- GOOD -->
  <div 
    class="static-class" 
    :class="[className, { 'static-class--modified': isModified }]">
  </div>
</template>
Maurici Abad
  • 1,012
  • 9
  • 20