vue-styled-components icon indicating copy to clipboard operation
vue-styled-components copied to clipboard

TypeScript Support?

Open u3u opened this issue 7 years ago β€’ 9 comments
trafficstars

u3u avatar Jul 25 '18 07:07 u3u

Very much I wait for TS support. Is not enough for this Frankenstein - https://github.com/DiFuks/vue.tsx

DiFuks avatar Aug 01 '19 19:08 DiFuks

I have no experience with TS, I've used only Flow type. If any of you are interested can submit a PR for this

liqueflies avatar Aug 05 '19 07:08 liqueflies

Very basic type definitions. Add to a <name>.d.ts file in your project: If you use tsx and have JSX.InstrinctElements defined somewhere you could swap HTMLElements for JSX.InstrinctElements.

declare module 'vue-styled-components' {
   import * as CSS from 'csstype';
   import * as Vue from 'vue';

   export type CSSProperties = CSS.Properties<string | number>;

   export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };

   export interface CSSObject extends CSSProperties, CSSPseudos {
       [ key: string ]: CSSObject | string | number | undefined;
   }

   export type CSS = CSSProperties;

   export type StyledComponent = Vue.Component & Vue.VueConstructor & {
       extend(cssRules: TemplateStringsArray, ...interpolate: TemplateStringsArray[]): StyledComponent
       withComponent(target: Vue.VueConstructor): StyledComponent
   }


   export type StyledComponentElements<T=HTMLElements> = {
       [k in keyof T]:  (str: TemplateStringsArray) =>StyledComponent
   }
   export type Styled<T=HTMLElements> = StyledComponentElements & {
       <T>(Component: T, props?:Record<string,Vue.PropOptions['type']>): (str: TemplateStringsArray) =>StyledComponent
   }

   export interface HTMLElements {
       a: HTMLAnchorElement
       abbr: HTMLElement
       address: HTMLElement
       area: HTMLAreaElement
       article: HTMLElement
       aside: HTMLElement
       audio: HTMLAudioElement
       b: HTMLElement
       base: HTMLBaseElement
       bdi: HTMLElement
       bdo: HTMLElement
       big: HTMLElement
       blockquote: HTMLElement
       body: HTMLBodyElement
       br: HTMLBRElement
       button: HTMLButtonElement
       canvas: HTMLCanvasElement
       caption: HTMLElement
       cite: HTMLElement
       code: HTMLElement
       col: HTMLTableColElement
       colgroup: HTMLTableColElement
       data: HTMLElement
       datalist: HTMLDataListElement
       dd: HTMLElement
       del: HTMLElement
       details: HTMLElement
       dfn: HTMLElement
       dialog: HTMLDialogElement
       div: HTMLDivElement
       dl: HTMLDListElement
       dt: HTMLElement
       em: HTMLElement
       embed: HTMLEmbedElement
       fieldset: HTMLFieldSetElement
       figcaption: HTMLElement
       figure: HTMLElement
       footer: HTMLElement
       form: HTMLFormElement
       h1: HTMLHeadingElement
       h2: HTMLHeadingElement
       h3: HTMLHeadingElement
       h4: HTMLHeadingElement
       h5: HTMLHeadingElement
       h6: HTMLHeadingElement
       head: HTMLElement
       header: HTMLElement
       hgroup: HTMLElement
       hr: HTMLHRElement
       html: HTMLHtmlElement
       i: HTMLElement
       iframe: HTMLIFrameElement
       img: HTMLImageElement
       input: HTMLInputElement
       ins: HTMLModElement
       kbd: HTMLElement
       keygen: HTMLElement
       label: HTMLLabelElement
       legend: HTMLLegendElement
       li: HTMLLIElement
       link: HTMLLinkElement
       main: HTMLElement
       map: HTMLMapElement
       mark: HTMLElement
       menu: HTMLElement
       menuitem: HTMLElement
       meta: HTMLMetaElement
       meter: HTMLElement
       nav: HTMLElement
       noscript: HTMLElement
       object: HTMLObjectElement
       ol: HTMLOListElement
       optgroup: HTMLOptGroupElement
       option: HTMLOptionElement
       output: HTMLElement
       p: HTMLParagraphElement
       param: HTMLParamElement
       picture: HTMLElement
       pre: HTMLPreElement
       progress: HTMLProgressElement
       q: HTMLQuoteElement
       rp: HTMLElement
       rt: HTMLElement
       ruby: HTMLElement
       s: HTMLElement
       samp: HTMLElement
       script: HTMLScriptElement
       section: HTMLElement
       select: HTMLSelectElement
       small: HTMLElement
       source: HTMLSourceElement
       span: HTMLSpanElement
       strong: HTMLElement
       style: HTMLStyleElement
       sub: HTMLElement
       summary: HTMLElement
       sup: HTMLElement
       table: HTMLTableElement
       tbody: HTMLTableSectionElement
       td: HTMLTableDataCellElement
       textarea: HTMLTextAreaElement
       tfoot: HTMLTableSectionElement
       th: HTMLTableHeaderCellElement
       thead: HTMLTableSectionElement
       time: HTMLElement
       title: HTMLTitleElement
       tr: HTMLTableRowElement
       track: HTMLTrackElement
       u: HTMLElement
       ul: HTMLUListElement
       var: HTMLElement
       video: HTMLVideoElement
       wbr: HTMLElement
   }

   export let styled: Styled;

   export default styled;
}

RobinRadic avatar Oct 18 '19 19:10 RobinRadic

maybe this declaration is more then better.

declare module 'vue-styled-components' {
  import * as CSS from 'csstype';
  import * as Vue from 'vue';

  export type CSSProperties = CSS.Properties<string | number>;

  export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };

  export interface CSSObject extends CSSProperties, CSSPseudos {
    [key: string]: CSSObject | string | number | undefined;
  }

  export type CSS = CSSProperties;

  type VueProps = {
    [propsName: string]: {
      type: new (...args: any[]) => unknown
      default?: unknown
      required?: boolean
      validator?(value: unknown): boolean;
    }
  } | {
    [propsName: string]: new (...args: any[]) => unknown
  }

  type PropsType<Props extends VueProps> = {
    [K in keyof Props]:
    Props[K] extends { type: new (...args: any[]) => unknown } ?
    InstanceType<Props[K]['type']>
    : Props[K] extends new (...args: any[]) => unknown ?
    InstanceType<Props[K]>
    : never
  }

  export type StyledComponent<Props extends VueProps> = Vue.Component & Vue.VueConstructor & {
    extend<U extends VueProps>(cssRules: TemplateStringsArray, ...interpolate: TemplateStringsArray[]): StyledComponent<Props & U>
    withComponent<V extends VueProps>(target: Vue.VueConstructor): StyledComponent<Props & V>
  } & { new(props: PropsType<Props>): Vue.Component }

  export type StyledComponentElements<T = HTMLElements> = {
    [k in keyof T]: (str: TemplateStringsArray) => StyledComponent<{}>
  }

  export type Component = HTMLElements | keyof HTMLElements | Vue.Component | Vue.VueConstructor

  export type Styled = StyledComponentElements & {
    <T extends Component, Props extends VueProps>(Component: T, props?: Props): (str: TemplateStringsArray, ...placeholders: ((props: PropsType<Props>) => string | String | { toString: () => string | String })[]) => StyledComponent<Props>
  }

  export interface HTMLElements {
    a: HTMLAnchorElement
    abbr: HTMLElement
    address: HTMLElement
    area: HTMLAreaElement
    article: HTMLElement
    aside: HTMLElement
    audio: HTMLAudioElement
    b: HTMLElement
    base: HTMLBaseElement
    bdi: HTMLElement
    bdo: HTMLElement
    big: HTMLElement
    blockquote: HTMLElement
    body: HTMLBodyElement
    br: HTMLBRElement
    button: HTMLButtonElement
    canvas: HTMLCanvasElement
    caption: HTMLElement
    cite: HTMLElement
    code: HTMLElement
    col: HTMLTableColElement
    colgroup: HTMLTableColElement
    data: HTMLElement
    datalist: HTMLDataListElement
    dd: HTMLElement
    del: HTMLElement
    details: HTMLElement
    dfn: HTMLElement
    dialog: HTMLDialogElement
    div: HTMLDivElement
    dl: HTMLDListElement
    dt: HTMLElement
    em: HTMLElement
    embed: HTMLEmbedElement
    fieldset: HTMLFieldSetElement
    figcaption: HTMLElement
    figure: HTMLElement
    footer: HTMLElement
    form: HTMLFormElement
    h1: HTMLHeadingElement
    h2: HTMLHeadingElement
    h3: HTMLHeadingElement
    h4: HTMLHeadingElement
    h5: HTMLHeadingElement
    h6: HTMLHeadingElement
    head: HTMLElement
    header: HTMLElement
    hgroup: HTMLElement
    hr: HTMLHRElement
    html: HTMLHtmlElement
    i: HTMLElement
    iframe: HTMLIFrameElement
    img: HTMLImageElement
    input: HTMLInputElement
    ins: HTMLModElement
    kbd: HTMLElement
    keygen: HTMLElement
    label: HTMLLabelElement
    legend: HTMLLegendElement
    li: HTMLLIElement
    link: HTMLLinkElement
    main: HTMLElement
    map: HTMLMapElement
    mark: HTMLElement
    menu: HTMLElement
    menuitem: HTMLElement
    meta: HTMLMetaElement
    meter: HTMLElement
    nav: HTMLElement
    noscript: HTMLElement
    object: HTMLObjectElement
    ol: HTMLOListElement
    optgroup: HTMLOptGroupElement
    option: HTMLOptionElement
    output: HTMLElement
    p: HTMLParagraphElement
    param: HTMLParamElement
    picture: HTMLElement
    pre: HTMLPreElement
    progress: HTMLProgressElement
    q: HTMLQuoteElement
    rp: HTMLElement
    rt: HTMLElement
    ruby: HTMLElement
    s: HTMLElement
    samp: HTMLElement
    script: HTMLScriptElement
    section: HTMLElement
    select: HTMLSelectElement
    small: HTMLElement
    source: HTMLSourceElement
    span: HTMLSpanElement
    strong: HTMLElement
    style: HTMLStyleElement
    sub: HTMLElement
    summary: HTMLElement
    sup: HTMLElement
    table: HTMLTableElement
    tbody: HTMLTableSectionElement
    td: HTMLTableDataCellElement
    textarea: HTMLTextAreaElement
    tfoot: HTMLTableSectionElement
    th: HTMLTableHeaderCellElement
    thead: HTMLTableSectionElement
    time: HTMLElement
    title: HTMLTitleElement
    tr: HTMLTableRowElement
    track: HTMLTrackElement
    u: HTMLElement
    ul: HTMLUListElement
    var: HTMLElement
    video: HTMLVideoElement
    wbr: HTMLElement
  }

  export let styled: Styled;

  export default styled;
}

kahirokunn avatar Feb 10 '20 10:02 kahirokunn

Any updates on this? It's been a couple months..

theoparis avatar Dec 22 '20 02:12 theoparis

any news?

silversonicaxel avatar Feb 06 '21 16:02 silversonicaxel

too type safe with @vue/composition-api

declare module "vue-styled-components" {
  import * as CSS from "csstype"
  import * as Vue from "vue"
  import { defineComponent, ExtractPropTypes } from "@vue/composition-api"
  type ExcludeArrayString<T> = T extends string[] ? never : T
  type VueProps = ExcludeArrayString<Parameters<typeof defineComponent>[0]["props"]>

  export type CSSProperties = CSS.Properties<string | number>

  export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject }

  export interface CSSObject extends CSSProperties, CSSPseudos {
    [key: string]: CSSObject | string | number | undefined
  }

  export type CSS = CSSProperties

  export type StyledComponent<Props extends VueProps> = Vue.Component &
    Vue.VueConstructor & {
      extend<U extends VueProps>(
        cssRules: TemplateStringsArray,
        ...interpolate: TemplateStringsArray[]
      ): StyledComponent<Props & U>
      withComponent<V extends VueProps>(target: Vue.VueConstructor): StyledComponent<Props & V>
    } & { new (props: ExtractPropTypes<Props>): Vue.Component }

  export type StyledComponentElements = {
    [k in keyof HTMLElementTagNameMap]: (str: TemplateStringsArray) => StyledComponent<{}>
  }

  export type Component = HTMLElementTagNameMap | keyof HTMLElementTagNameMap | Vue.Component | Vue.VueConstructor

  export type Styled = StyledComponentElements & {
    <T extends Component, Props extends VueProps>(Component: T, props?: Props): (
      str: TemplateStringsArray,
      ...placeholders: ((props: ExtractPropTypes<Props>) => string | String | { toString: () => string | String })[]
    ) => StyledComponent<Props>
  }

  export let styled: Styled

  export default styled
}

https://gist.github.com/katsuyaU/e371399f411baba78dc9a43d3303e995

example


import { PropType } from "@vue/composition-api"
import styled from "vue-styled-components"

interface Hoge {
  fuga: number
}

styled("a", {
  requiredProp: { type: String, required: true },
  optionalProp: { type: String },
  objectProp: { type: Object as PropType<Hoge> },
})`
  height:  ${props => props.requiredProp}px;

`
γ‚Ήγ‚―γƒͺγƒΌγƒ³γ‚·γƒ§γƒƒγƒˆ 2021-03-07 11 24 46

kagurazaka-0 avatar Mar 07 '21 02:03 kagurazaka-0

A problem arises injectglobal type How to solve it?

unseoJang avatar May 25 '22 01:05 unseoJang

What about typing literal strings ? ex:

type MyCompProps = { value: 'value1' | 'value2'; }

danieltvaz avatar Jun 02 '22 20:06 danieltvaz