frenic / csstype

Strict TypeScript and Flow types for style based on MDN data
MIT License
1.73k stars 72 forks source link

[Help wanted] How to apply csstype on an interface #53

Closed stephenkoo closed 6 years ago

stephenkoo commented 6 years ago

I have an object that must only contain specific css properties:

export interface InterfaceTypeElementProperties {
  fontFamily?: string;
  fontSize?: [string, number];
  fontWeight?: number;
  letterSpacing?: number;
  textTransform?: string;
  lineHeight?: number | number[];
  marginTop?: number | number[];
  marginBottom?: number | number[];
}

I'm hoping to apply csstypes on top of those properties - for instance fontWeight shouldn't just accept any number, but those recognised by csstype.

What's the right way to do this? Thank you!

frenic commented 6 years ago

I would prefer using the Pick type utility in every way I can. However, there's an issue about loosing the JSDoc for each property by using mapped types. So it isn't perfect. But hopefully that will be fixed soon enough.

import * as CSS from "csstype";
type InterfaceTypeElementProperties = Pick<CSS.Properties, "fontFamily" | "fontSize" | "fontWeight" | "letterSpacing" | "textTransform" | "lineHeight" | "marginTop" | "marginBottom">;

You can also explicitly use the type value if you don't care about the JSDoc at all.

export interface InterfaceTypeElementProperties {
  // ...
  fontWeight?: CSS.Properties['fontWeight'];
  // ...
}
frenic commented 6 years ago

I don't know if I understood you correctly. But if you want to extend InterfaceTypeElementProperties your only option is to explicitly use the type value otherwise TS will complain that they don't match.

export interface InterfaceTypeElementProperties {
  // ...
  fontWeight?: number | CSS.Properties['fontWeight'];
  // ...
}
stephenkoo commented 6 years ago

I'm still learning TypeScript so I wasn't aware Pick existed, thank you.

I think

export interface InterfaceTypeElementProperties {
  // ...
  fontWeight?: CSS.Properties['fontWeight'];
  // ...
}

gives me the intended effect, thank you.

Just out of curiosity, is there a better way to write this using a combination of Pick (to select the desired properties) and Partial (to make the selected properties optional)?

frenic commented 6 years ago

You don't need Partial because all properties are already optional in CSS.Properties. Pick is all you need.

stephenkoo commented 6 years ago

Ah perfect. Thanks!