Learning TypeScript

Note: I originally posted this on Medium.

I’ve been learning TypeScript for a couple of weeks now, and I love it, but trying to understand the compiler errors can really slow me down. They are awesome error messages, because they are exact and verbose, but it can be overwhelming and difficult to parse with my eyes and brain. I was tinkering with a library called react-popper and decided to add some inline styles via the Reactstyles property:

import * as React from "react"
import * as ReactDOM from "react-dom"
import { Hello, HelloStyled, HelloTriangle, HelloProps } from "./components/Hello"
import { Manager, Target, Popper, Arrow } from 'react-popper'
const mainStyle = {
  display: 'flex',
  // alignItems: 'center',
  // justifyContent: 'center',
  margin: '100px'
}
type Main = (children?: any) => JSX.Element
const Main: Main = ({children}) =>
  <div style={mainStyle}>{children}</div>
//...additional code not shown

This snippet threw the following TypeScript compiler error:

TS2322: Type '{ style: { display: string; alignItems: string; justifyContent: string; margin: string; }; childr...' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
  Type '{ style: { display: string; alignItems: string; justifyContent: string; margin: string; }; childr...' is not assignable to type 'HTMLAttributes<HTMLDivElement>'.
    Types of property 'style' are incompatible.
      Type '{ display: string; alignItems: string; justifyContent: string; margin: string; }' is not assignable to type 'CSSProperties'.

I have learned to look at the last line of the error messages first:

Type '{ display: string; alignItems: string; justifyContent: string; margin: string; }' is not assignable to type 'CSSProperties'.

Basically, this message is telling me that an object that I have defined with the display, alignItems, justifyContent, and margin properties cannot be assigned to a type of CSSProperties. Since my IDE is setup to jump to definitions, I can navigate to the definition of CSSProperties, which is defined in @types/react, the TypeScript declaration file for React. Here is the beginning of the CSSProperties type declartion from that link:

// This interface is not complete. Only properties accepting
    // unitless numbers are listed here (see CSSProperty.js in React)
    interface CSSProperties {
        /**
         * Aligns a flex container's lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.
         */
        alignContent?: CSSWideKeyword | "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "stretch";

        /**
         * Sets the default alignment in the cross axis for all of the flex container's items, including anonymous flex items, similarly to how justify-content aligns items along the main axis.
         */
        alignItems?: CSSWideKeyword | "flex-start" | "flex-end" | "center" | "baseline" | "stretch";

You can see that CSSProperties is a TypeScript interface with a lot of CSS properties defined as specific types. For example CSSProperties.alignItems is a union type between CSSWideKeyword, 'flex-start', 'flex-end', etc. At this point I didn’t know what was wrong with my code - the alignItems property was spelled correctly and was the correctCase, and it’s value, 'center', a string literal type were “correct” - no obvious spelling errors or silly typos. This is one of those times where I start to question my sanity. Is what I see even real? It wasn’t until I (somewhat randomly) tried importing React.CSSProperties and explicitly defining my custom object of that type, that the error message went away:

const mainStyle: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  margin: '100px'
}

So, while my object was “correct” in structure (at least it appeared to be correct), it was not technically the same type structure as the CSSProperties type. I think the error was thrown because the values of my mainStyle object were technically just string types, rather than specify string literal types, such as 'center'. So, I suppose, when in doubt, try explicitly assigning a type to your variables.

comments powered by Disqus