1

I'v faced a problem trying to define an interface for the following structure:

interface JSONRecord {
  [propName: string]: any;
}
type ReturnType = (id: string|number, field: string, record: JSONRecord) => string

export const formatDictionary = ({
  mode = "render", key = "originalValue",
  defaultKey = "originalValue"
}):ReturnType => (id, field, record) => {
  ...
}

interface Lookup {
  Dictionary: ({mode, key, defaultKey}:{mode: string, key: string, defaultKey: string}) => ReturnType,
  ...
}
export const functionLookup:Lookup = {
  Dictionary: formatDictionary,
  ...
}
export const formatField = (params:JSONRecord):string|ReturnType => {
  const type:string = params.type
  if (type === undefined) { return identity }
  const fn = functionLookup[type]
  if (fn === undefined) { return identity }
  return fn({ ...params })
}

I'm getting the following errors:

  1. In line const fn = functionLookup[type] : Element implicitly has an 'any' type becasue expression of type string can't be used to index type 'Lookup'. No index signature with parameter of type 'string' was found on type 'Lookup'.
  • I'm not really sure why is this happening, i thought that the Dictionary i defined in Lookup is supposed to be interpreted as a string. When i change Dictionary to [x: string]: ({mode, key, defaultKey}:{mode: string, key: string, defaultKey: string}) => ReturnType the error disappears, but i want to be specific with the arguments that can be passed.
  1. In line return fn({ ...params }) : Expected 3 arguments, but got 1
  • I can't really wrap my head around this, the function is clearly expecting only 1 object as an argument {mode, key, defaultKey} or is it expecting the ReturnType function there?

I would appreciate any help. Thanks a lot in advance :)

2
  • please share reproducable example. identity is not defined variable Commented Apr 15, 2021 at 10:01
  • Hi @captain-yossarian Thanks for your answer. I'v created a codesandbox with a much simpler example that results in the same error. codesandbox.io/s/0p1od?file=/index.ts i still can't understand what's going on Commented Apr 15, 2021 at 10:20

1 Answer 1

1

In you case (from sandbox):

const anExampleVariable = "Hello World"
console.log(anExampleVariable)

// To learn more about the language, click above in "Examples" or "What's New".
// Otherwise, get started by removing these comments and the world is your playground.

interface Lookup {
    test: number
}
const functionLookup:Lookup = {
    test: 5
}

const params = {
    type: 'test'
};
const type = params.type
const a = functionLookup[type]

params variable is infered as {type: string}.

Here functionLookup[type] you want use type as index for functionLookup, but TS does not work that way. Because you can't just use general type string as index for Lookup type.

Lookup allows you to use only literal test as index.

So you can add as const prefix to your params vvariable.

const params = {
    type: 'test'
} as const;

You can make Lookup indexed:

interface Lookup {
    test: number,
    [prop:string]:number
}

Or, you can explicitly define a Record type for params:


const params:Record<string, keyof Lookup> = {
    type: 'test'
}
Sign up to request clarification or add additional context in comments.

2 Comments

I understand now where i got lost there, but isn't it just saying now that every string is now acceptable and will be looked for in the functionLookup? so i should expect undefined value if the wrong string is passed?
It depends on your logic. If you will stick with [prop:string]:number, then - yes. Value can be undefined. If U dont want undefined value, then U probable should use Record<string, keyof Lookup>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.