gcanti / io-ts-codegen

Code generation for io-ts
https://gcanti.github.io/io-ts-codegen/
MIT License
156 stars 14 forks source link

Option<T> etc #12

Closed leemhenson closed 6 years ago

leemhenson commented 6 years ago

From browsing it looks like things from io-ts-types aren't built in here yet. What would be the best way of generating Option types such as:

export const Person = t.interface({
  telephone: createOptionFromNullable(t.string),
});

export interface Person {
  telephone: Option<string>;
}
gcanti commented 6 years ago

I can think of two options:

(1) importing the type and then referencing it with Identifier

const d = t.typeDeclaration('Person', t.interfaceCombinator([t.property('telephone', t.identifier('OptionString'))]))

const prelude = `import { OptionString } from './my-types'`

const result = `
${prelude}

// == generated by io-ts-codegen ==

${t.printStatic(d)}

${t.printRuntime(d)}
`

Result

import { OptionString } from './my-types'

// == generated by io-ts-codegen ==

interface Person {
  telephone: OptionString
}

const Person = t.interface({
  telephone: OptionString
})

(2) using a CustomTypeDeclaration instead of importing the type

const createOptionFromNullable = (type: t.TypeReference, name: string): t.CustomTypeDeclaration => {
  return t.customTypeDeclaration(
    name,
    `type ${name} = Option<${t.printStatic(type)}>`,
    `const ${name} = createOptionFromNullable(${t.printRuntime(type)})`
  )
}

const declarations = [
  t.typeDeclaration('Person', t.interfaceCombinator([t.property('telephone', t.identifier('OptionString'))])),
  createOptionFromNullable(t.stringType, 'OptionString')
]

// apply topological sort in order to get the right order
const sorted = t.sort(declarations)

const result = sorted
  .map(
    d => `
${t.printStatic(d)}

${t.printRuntime(d)}
`
  )
  .join('')

Result

type OptionString = Option<string>

const OptionString = createOptionFromNullable(t.string)

interface Person {
  telephone: OptionString
}

const Person = t.interface({
  telephone: OptionString
})

Currently there's no way to inline a custom type as per your example, is this a problem?

leemhenson commented 6 years ago

Hey Giulio. CustomTypeDeclaration works really nice! I'm happy to alias OptionString as suggested.