DEV Community

Cover image for TIL: October 2020
Alecell
Alecell

Posted on • Updated on

TIL: October 2020

Day 05 [Typescript/Redux] - How to type an dispatched action that returns a value with redux-thunk, react-hooks and typescript

To get access to the returned value of a ThunkAction inside dispatch that don't pop any type errors you should declare the the type when initiate the dispatch.

const dispatch = useDispatch<MyDispatchType>();
Enter fullscreen mode Exit fullscreen mode

The generics define the retuned value of the dispatch, but the generic type should be of type ThunkDispatch.

ThunkDispatch receive 3 arguments, but to our case we just need to care about the first one, which is relative to the return type of the dispatch.

type MyDispatchType = ThunkDispatch<MyType, any, AnyAction>
Enter fullscreen mode Exit fullscreen mode

Obs: ThunkDispatch is exported from redux-thunk and AnyAction is exported from redux.

With this, when you use the dispatch function it will provide autocomplete and a type-safe return based on MyType.

Full example:

interface MyType {
  foo: number;
  bar: string;
  baz: string;
}

type MyDispatchType = ThunkDispatch<MyType, any, AnyAction>;

const myAction = (status: boolean) => (dispatch): MyType => {
  dispatch({ type: "foo", payload: { status } });
  return {
    foo: 23,
    bar: 'naruto',
    baz: 'hokage',
  }
}

function MyComponent() {
  const dispatch = useDispatch<MyDispatchType>();

  const handleClick = () => {
    //  No errors
    const { foo, bar, baz } = dispatch(myAction(true));
  }

  return (
    <button onClick={handleClick}>CLICK ME</button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Day 07 [Javascript] - How to return a value that is accessible only inside/after an event

One of the gold questions of the Javascript past is now solved surprisingly easy, thanks to the Promises.

So, imagine a scenario that your user add an audio file to an input and, before you upload the audio, for some reason, you need to get that audio duration. Before Promises it was impossible to achieve without bad practices or code smells since you only can get an audio duration after it was loaded, but with promises we can keep our code clean and do the trick.

As I found here promises could be used to return the value inside an event (which is pretty obvious BTW) so, on the case that we need to return the audio duration of a File when onloadedmetadata event is fired, we can do this:

  static async getAudioFileDuration(file: File): Promise<number> {
    return new Promise((resolve, reject) => {
      const objectUrl = URL.createObjectURL(file);
      const audio = new Audio(objectUrl);

      audio.onloadedmetadata = (e: any) => {
        resolve(audio.duration);
      };
    });
  }
Enter fullscreen mode Exit fullscreen mode

The best of this approach is to avoid many work around on the web like have a variable in the upper scopes of the methods, send a callback or do what you wanted to be outside of the event inside of it. The Promise method keep the best practices, its modular, reusable and clean to read.

Day 12 [CSS] - How to justify-self with flex

(Okay, I's embarrassing I did no know this before, BUT...)

I tried to answer this StackOverFlow question and realize (besides answering the question wrongly) I didn't know how to answer, what makes me think "Hey, I don't know the answer", and start to search.

The point is that for needing purposes, the property justify-self don't work on flex items because we can just use the margin proprty to reach the same behavior.

So, when need justify-self: flex-end, just replace this with margin-left: auto.

I create a pen to exemplify this.

Day 15 [Typescript] - Why we have to reference dynamic types with the name of the type, and not only the type?

Delving on the web these days I figure out a answer that I don't get that I have already: Why we have to write dynamic keys like this:

interface Foo {
  [key: string]: string;
} 
Enter fullscreen mode Exit fullscreen mode

instead of:

interface Bar {
  [string]: string;
}
Enter fullscreen mode Exit fullscreen mode

For too long I thought it was a typescript limitation, but I was wrong (maybe not btw), this exists for reading purposes, since name the key with something more clear is way more readable than just key.

interface Foo {
  [itemName: string]: string;
}
Enter fullscreen mode Exit fullscreen mode

Now I'll stop to name the dynamic keys with just key and give them an appropriate name, and you should do it too. (if you don't do already of course)

Day 20 [Typescript] - Get the type of deeply nested dynamic key types

Let's suppose we have a collection of objects like this:

interface Item {
  name: string;
  price: number;
}

interface ItemCollection {
  [itemId: string]: Item;
}
Enter fullscreen mode Exit fullscreen mode

So we have a collection of Items that each one of the collection is its itemId.

Now, again, for some reason we need to get the type of Item by the collection, without reference the Item directly.

How can we get access to the type of each item of ItemCollection, to, let's say, create an type alias?

type TypeAlias = ItemCollection[string];
Enter fullscreen mode Exit fullscreen mode

And that's it, is really easy to reference the type nested, you just need to use the type of the key as you would use the type reference directly, but not using the name, but the type itself.

Day 30 [Typescript/React] - Correctly type SVG to use as components

For too long I wonder how to properly type SVG images when use ReactSvg or something like this, saddly I don't save the reference, but I found this:

  React.FC<React.SVGProps<SVGSVGElement>>;
Enter fullscreen mode Exit fullscreen mode

So, when use it on the declarations, make something like this:

declare module '*.svg' {
  const content: React.FC<React.SVGProps<SVGSVGElement>>;
  export = content;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)