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

Typescript output? #174

Open
StevenLangbroek opened this issue Nov 16, 2018 · 14 comments
Open

Typescript output? #174

StevenLangbroek opened this issue Nov 16, 2018 · 14 comments

Comments

@StevenLangbroek
Copy link

StevenLangbroek commented Nov 16, 2018

I see there's no option for outputting typescript, but formats look relatively straightforward to write. Would you be interested in a typescript formatter?

Thanks!

@trazek
Copy link
Contributor

trazek commented Nov 17, 2018

I'd be interested in seeing what that looks like.

@StevenLangbroek
Copy link
Author

I'd be interested in seeing what that looks like.

Initially probably not that different from the common.js one. I'm still exploring Theo though, so depending on how it works it might be interesting to output an enum or union per category.

@aputinski
Copy link
Contributor

Yeah, I think Typescript could be interesting if we can output a format that is useful for everyone.

@petekp
Copy link

petekp commented Dec 8, 2018

Our design system uses TypeScript and I wanted to leverage autocomplete in VSCode when referencing Theo-generated styles/themes in React components. The quickest solution was to auto-generate typings for the JS module using tsc and its --declaration flag. Example output: https://gist.github.com/petekp/8e706a272b7999e20ea7146b77fd42d8

It only generates the primitive types, e.g. string, number, etc. which has been sufficient for autocompleting theme properties. These annotations could be further refined to specific tokens, but I haven't found this necessary just yet.

@trazek
Copy link
Contributor

trazek commented Dec 8, 2018

@petekp that link gave me a 404.

@petekp
Copy link

petekp commented Dec 8, 2018

@trazek Oops, fixed :)

@mattfelten
Copy link

@petekp Could you walk through how you generated the typings for that? tsc --declaration tokens.js doesn't love that it's not a TS file.

@petekp
Copy link

petekp commented May 29, 2019

@mattfelten I'm currently faking it by registering a custom format (.d.ts) and outputting the style data but wrapped in a typings export declaration; basically gluing together the same output tsc --declaration would emit:

// Convert styles to JS and sort them by category
const categorizeStyles = (styleMap: ImmutableStyleMap) => {
  const styleProps: ThemeStyle[] = styleMap.get('props').toJS()
  return chain(styleProps)
    .sortBy('name')
    .groupBy('category')
    .value()
}

// Convert styles into an easily consumable JS object ("theme")
export const createThemeObjectFromStyles = (
  styleData: ImmutableStyleMap
): Readonly<Theme> => {
  return Object.entries(categorizeStyles(styleData)).reduce(
    (acc, [category, styles]) => ({
      ...acc,
      ...styles.reduce((acc2, style) => {
        return {
          ...acc2,
          [style.name]: style.value,
        }
      }, {}),
    }),
    {}
  )
}

// Create a `.d.ts` file and inject the theme object with typings export declaration
theo.registerFormat(
    'd.ts',
    styleMap =>
      `export declare const _default: 
        ${JSON.stringify(createThemeObjectFromStyles(styleMap))}
      `
  )

@mattfelten
Copy link

Ah that's clever. I ended up registering a new ts format and then running tsc on it.

module.exports = theo => {
	theo.registerFormat(
		"ts",
`
// Source: {{stem meta.file}}
const tokens = {
	{{#each props}}
	{{camelcase name}}: '{{value}}',
	{{/each}}
};
export default tokens;
`
	);
}

@petekp
Copy link

petekp commented May 29, 2019

@mattfelten Nice! Before my current method I was using my node build script to change the filename from .js->.ts, run tsc --declarations and then change it back to .js 😄

It would be cool to build TS typing support into Theo, perhaps either as an officially supported format on its own (.d.ts), as an option for a .ts format, or perhaps a CLI flag (--tsDeclarations). The latter might be more amenable for custom JS-based formats.

@aputinski
Copy link
Contributor

I'll just chime in and say that I don't have any plans to add TypeScript support, but I'd happily accept a PR for it.

@petekp
Copy link

petekp commented May 31, 2019

I'm down to help implement this. Still wondering what exactly folks would expect from this format. Just definitions? Auto-generated types/interfaces? Thinking optionally outputting .d.ts definitions for the built-in JS format(s) would be a reasonable place to start.

@mattfelten
Copy link

That’s what I would expect. That the output can be packaged and “just work” in typescript projects. I don’t think we would need actual .ts files

@WickyNilliams
Copy link

I used the following which output a TS declaration which matches the module.js theo format:

const {
  pipe,
  get,
  map,
  camelCase,
  method,
  sortBy,
  join,
} = require("lodash/fp");

const toConstDeclaration = ({ name, value }) =>
  `export declare const ${camelCase(name)} = ${JSON.stringify(value)}`;

module.exports = pipe(
  method("toJS"),
  get("props"),
  sortBy("name"),
  map(toConstDeclaration),
  join(";\n")
);

You can then register this in your setup file:

const typescriptFormat = require("./formats/typescript")

module.exports = theo => {
	theo.registerFormat("d.ts", typescriptFormat)
}

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

6 participants