1

I've tried this every which way I can think of, and I did look at other similar posts regarding recursive types, but I haven't been able to create a type that works recursively for this case.

What I want is for this type to accept partial properties of CSSStyleDeclaration, and, for any properties not matching a property of CSSStyleDeclaration, I want it to map back to the type itself.

This seems to work only for the first level:

interface NestedCSSDeclarations {
    [name: string]: CSSDeclaration;
}

type CSSDeclaration = {
    [P in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[P];
} & NestedCSSDeclarations

function css(obj: CSSDeclaration) {
    // ...
}

let style = {
  headline: css({
    color: "red",
    h1: {
      color: "blue",
      "&:hover": {
        color: "green"
      }
    },
    "@media screen and (min-width: 400px)": {
      h1: {
        fontSize: "50px"
      }
    }
  })
}

Is there no way to type-hint this?

1 Answer 1

2

If you use | operator instead of & it will work fine

type CSSDeclaration = {
    [P in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[P];
} | NestedCSSDeclarations
Sign up to request clarification or add additional context in comments.

2 Comments

It appears you're right, but... this doesn't mesh with my understanding of the | and & type-operators. Normally I use the | operator for type alternatives, e.g. number | string which means it's either and can't be both. I thought the & operator was for combined types, e.g. Foo & Bar means it has to be both. Can you explain why this works?
Because it can't be both at the same time in your case, nested CSS identifier like &:hover isn't the same as a CSS property like color

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.