Rotem Revivo
Rotem Revivo

Reputation: 13

Typescrit interface for an object of arrow functions

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'.
  1. In line return fn({ ...params }) : Expected 3 arguments, but got 1

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

Upvotes: 1

Views: 286

Answers (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'
}

Upvotes: 1

Related Questions