Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Generics and static types #615

Open
maljac opened this issue Oct 28, 2021 · 5 comments
Open

Question: Generics and static types #615

maljac opened this issue Oct 28, 2021 · 5 comments

Comments

@maljac
Copy link

maljac commented Oct 28, 2021

I read the documentation and was not sure how I can extract a generic static type from a generic io-ts type:

// the io-ts type definition

const TConfigValue = <C extends t.Mixed>(codec: C) =>
  t.type({
    value: codec,
    override: t.boolean
  })

I was only able to generate specific static types:

const TConfigValueNumber = TConfigValue(t.number)
type ConfigValueNumber = t.TypeOf<typeof TConfigValueNumber>

How can I get a static generic type like this:

type ConfigValue<T> = {
  value: T,
  override: boolean
}
@mlegenhausen
Copy link
Contributor

mlegenhausen commented Oct 29, 2021

In this case you can not use t.TypeOf you need instead to define all interfaces by yourself.

export interface ConfigValue<T> {
  value: T
  override: boolean
}
export interface ConfigValueC<TC extends t.Mixed> extends t.Type<TConfigValue<t.TypeOf<T>>, TConfigValue<t.OutputOf<T>>, unknown> {}
export function ConfigValue<TC extends t.Mixed>(codec: TC): ConfigValueC<TC> {
  return t.type({
    value: codec,
    override: boolean
  })
}

@maljac
Copy link
Author

maljac commented Nov 5, 2021

Thank you Malte. This helped a lot. Because your answer is not 100% correct, for further reference the final solution I came up with:

type ConfigValue<T> = {
  value: T;
  override: boolean;
};

interface ConfigValueC<TC extends t.Mixed> extends t.Type<ConfigValue<t.TypeOf<TC>>, ConfigValue<t.OutputOf<TC>>, unknown> {}

function createConfigValueT<TC extends t.Mixed>(codec: TC): ConfigValueC<TC> {
  return t.type({
    value: codec,
    override: t.boolean,
  });
}

The issue can be closed.

@mlegenhausen
Copy link
Contributor

You are welcome Malte 😉

@mrdulin
Copy link

mrdulin commented Feb 22, 2023

@mlegenhausen I have the same issue.

define all interfaces by yourself

Does it make people define the properties twice? io-ts runtime generic type and TS generic type?

@edwardaskew
Copy link

It's a little hacky but this worked for me:

const TConfigValue = <C extends t.Mixed>(codec: C) =>
  t.type({
    value: codec,
    override: t.boolean
  });

type ConfigValue<T> = t.TypeOf<ReturnType<typeof TConfigValue<t.Type<T>>>>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants