0

I'm new to TypeScript and can't mentally parse its syntax -- I'm a backend engineer, so I don't spend much time with JavaScript/JavaScripty-languages. I've tried searching, but I can't find anything that details what I'm seeing (and because I'm new to the language, I'm probably not using the correct terms).

In the following code, what am I looking at?

/**
 * `makeStyles` where the passed `styles` do not depend on props
 */
export default function makeStyles<Theme = DefaultTheme, ClassKey extends string = string>(
  style: Styles<Theme, {}, ClassKey>,
  options?: Omit<WithStylesOptions<Theme>, 'withTheme'>
): (props?: any) => ClassNameMap<ClassKey>;

https://github.com/mui-org/material-ui/blob/9bd4277ecd660ebe2fd4cb08960f58e98ddb6d43/packages/material-ui-styles/src/makeStyles/makeStyles.d.ts

I understand the export default function funcName, but after that I'm less sure. This is what my brain sees:

// default named export for renaming hijinks
export default function

// function name, type annotated argument list?
makeStyles<Theme = DefaultTheme, ClassKey extends string = string> 
(
  // property being passed to property name with typed annotation on argument?
  style: Styles<Theme, {}, ClassKey>,

  // 'options' are optional in the interface, so when passing this argument we also have to include '?' ?
  options?: Omit<WithStylesOptions<Theme>, 'withTheme'>
// if there are any 'props' (which are optional in the interface), we bind as props on the return type of 'ClassNameMap'
): (props?: any) => ClassNameMap<ClassKey>;

but that's probably wrong. Can you help me understand the components or help with the vocabulary needed to learn?

2
  • The <...> syntax should be familiar to you if you are a backend engineer because it is the same in Java, C++, C#, Ruby etc. Commented Jul 12, 2020 at 1:02
  • @slebetman the part that i was missing was that i was in a typescript definition and that it was a typename identifier and not picking characters to avoid special meaning in javascript. it's also not a thing in C++ to assign a default in the type identifier Commented Jul 12, 2020 at 3:12

2 Answers 2

2

It is a lot to unpack, here it is line by line.

export default function

Your spot on about this line. Just exporting the function to make it available elsewhere in the program.

makeStyles<Theme = DefaultTheme, ClassKey extends string = string>

Here makeStyles is the name of the function.

What's in between the <> is the generic arguments that it takes. Typescript Generics let you write functions that can take a variety of types as arguments. For example:

function identity<T>(arg: T): T {
    return arg;
}

The argument here is arg: T, which means arg must be of type T, and the return is typed with (): T, this second :T after the closing bracket indicates the return type of the function. So the argument and the return of this function must be of the same type.

So in our example the makeStyles function takes a generic argument of Theme and ClassKey. Generics also let you specify default values for these arguments if they aren't explicitly passed in. So where you see:

<Theme = DefaultTheme, ClassKey extends string = string>

If the values are not defined when the function is invoked, then Theme will be of type DefaultTheme, and ClassKey will be of type string.

The other piece there is that ClassKey extends string. That just means that it inherits all the string properties within it's type.

Then we have the arguments themselves here:

(
  style: Styles<Theme, {}, ClassKey>,
  options?: Omit<WithStylesOptions<Theme>, 'withTheme'>
)

style is the first argument. It's of type Styles which is also a generic type that takes three arguments. You may want to look up the Styles interface or type to see what that looks like to get more clarification. Here is an example of what it could look like:

interface Styles<ThemeType, AppType, ClassKeyType> {
     theme: ThemeType;
     app: AppType;
     classKey: ClassKeyType;
     .... a bunch of other properties for the styles type.
}

With Generics you can pass in a variety of types, which makes things more flexible. And the typescript compiler is smart enough to enforce this within your code depending on how things were invoked or instantiated.

options is the second argument. You are correct about the ?, that signifies that it is an optional argument. If it is not passed in, it will just be undefined. Here we are using a special typescript type called Omit. Omit will take a type as it's first argument, and a key of that type as the second argument. It will return a new type that has all the properties of the original type you passed in as the first argument, EXCEPT, the key that you passed in as the second argument.

Here WithStyleOptions is another generic type, like styles. It takes Theme as it's argument. From there Omit will take that type, and produce a new type, and exclude the withTheme property.

Then we have:

: (props?: any) => ClassNameMap<ClassKey>;

This last piece is typing the return type of the function. In this case, this function will return another function.

The new function it returns will take one argument named props which will have a type of any. any in typescript means what you would think, it could literally be anything. This function will have a return type of ClassNameMap, which is another generic.

For sure take a look at all the generics you are using here, and see how they are defined. That should help. Also see where the makeStyle function is called, I think seeing it from the other side will also be helpful.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the response and for helping me! > ClassKey extends string = string -- where this is a default, does it default to the empty value for a string? e.g. does this default to ""?
ClassKey extends string = string is only referring to the type, not the value. So ClassKey will extend the object string and get all of it's properties, or if ClassKey is not passed in, ClassKey will just be of type string and have all those properties. Glad this helped!
The parts inside <..> are not arguments to the function. They are templates for types that the function operate on just like in Java and C++. Therefore ClassKey cannot default to a value such as an empty string. It can only default to a type and in this case it defaults to type string as denoted by = string
0

This is just a type defintion (everything in the .d.ts file should just be definitions). Everything is typing.

The angle brackets <> after the function name indicate it is a generic function, which means you can specify a specifically typed instance of makeStyles. The = is for providing default types.

Next is the parameters, surrounded by (). These are just named parameters with their type annotations. Yes, ? indicates the parameter is optional. Omit is a utility type that will drop the specified key from the type.

The : after the parentheses is for the return type. In this case, this function returns a function. The syntax for returning a function is (parameter: parameterType) => returnType.

// default named export
export default function

// generic function with default types
makeStyles<Theme = DefaultTheme, ClassKey extends string = string> 
(
  // parameter with typed annotation
  style: Styles<Theme, {}, ClassKey>,

  // option parameter, Omit is a TypeScript global utility,
  // takes everything but 'withTheme' from WIthStylesOptions<Theme>
  options?: Omit<WithStylesOptions<Theme>, 'withTheme'>
// returns a function that takes props and returns a ClassNameMap<ClassKey>
): (props?: any) => ClassNameMap<ClassKey>;

2 Comments

Ah, I was also missing that this is strictly a header/definition. Great answer, concise and helpful! I voted up the answer, but lack the rep for it to be visible. Thank you!
@fartsandcrafts thanks. As the asker of the question, you can mark the answer as accepted.

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.