Dellirium
Dellirium

Reputation: 1516

Typescript how to mix dynamic([key: type]: type) and static typing for an interface

Main issue

Not really sure if this is possible, but since i abhor Typescript and it is making my coding hard I figured I'd ask just to make sure.

interface ISomeInterface {
  handler: () => {}
  [key: string]: string
}

Problem obviously is, the handler is a () => {} and not a string, so typescript throws an error. Is it possible to somehow make this work?

Addendum:

While on the topic, this interface is suppose to be consumed by a React.Context and since a requirement of a default value by React.createContext(/* requires default here */), I need to give it a object that matches that interface. When I attempt to pass an object litteral as such:

React.createContext({handler: () => {throw new Error('using default context')}})

Typescript is making a ruckus by saying {handler: () => never} cannot be assigned to {handler: () => {}} any way to make this interface plausible? I tried to make interface implement () => any, still didn't work, it wants explicit never.

Edit #1:

So i've made some changes, namely:

interface IFormContext {
  $handleChange: (key?, val?) => void
  $registerField: (key?) => void
  [key: string]: { value: string } | ((key?, val?) => void)
}

But now when I am trying to access the field like this: const {[key]: { value }} = props which is basically de-structuring with a dynamic key, i get the following error:

Property 'value' does not exist on type '{ value: string; } | ((key?: any, val?: any) => void)'.ts(2339)

Upvotes: 5

Views: 2356

Answers (1)

Alykam Burdzaki
Alykam Burdzaki

Reputation: 694

Unfortunately your named properties must match the index signature. In this case, since at least one property is a function, you can use:

[key: string]: string | Function;

or

[key: string]: any;

Both should work.

For your addendum, () => {} means a function with no arguments that returns a empty object, while the function () => {throw new Error('using default context')} is returning nothing, thus the error. There is a little bit of confusion with the braces used in types and in the actual function implementation.

A function with the type () => {} is actually something like () => {return {}} or () => ({}).

For a function that returns nothing you can use never or void, but if your handler may return something, you can use something like handler: () => void | boolean, replacing boolean by the type it may return.

Upvotes: 6

Related Questions