skip to Main Content

Consider this code:

IAppStateProps.ts:

import {INoteProps} from "./INoteProps";

export interface IAppStateProps {
  notesData: INoteProps[];
}

then use it here:
useAppState.ts:

import {INoteProps} from "./interfaces/INoteProps";
import {IAppStateProps} from "./interfaces/IAppStateProps";
export const useAppState = (): IAppStateProps => {
  const [notesData, setNotesData] = useState<INoteProps[]>([]);
  ...more code
  return {
    notesData
  }
};

My question is, since I defined the return type of useAppState to be IAppStateProps, and it knows that notesData should return INoteProps[], is it necessary to define the return type again in const [notesData, setNotesData] = useState<INoteProps[]>([]);?

2

Answers


  1. If I understand correctly the question. No, you don’t need to specify it.
    When you invoke useAppState it should return an object that has property notesData which is an array.

    Login or Signup to reply.
  2. since I defined the return type of useAppState to be IAppStateProps, and it knows that notesData should return INoteProps[], is it necessary to define the return type again in const [notesData, setNotesData] = useState<INoteProps[]>([]);?

    Yes. TypeScript can’t infer it in the direction you’re describing. If you leave the type argument off the call to useState and you use an empty array like that as the intial value, TypeScript will infer never[] as the type, which means you wouldn’t be able to call setNotesData with real data:

    // Stand-in for `INoteProps`, since it's not defined in the question
    interface INoteProps {
        something: string;
    }
    // ...
    export const useAppState = (): IAppStateProps => {
        const [notesData, setNotesData] = useState([]);
    
        useEffect(() => {
            setNotesData([
                {something: "cool"} // <== Error: Type '{ something: string; }' is 
                                    // not assignable to type 'never'. (2322)
            ])
        }, []);
    
        return {
            notesData
        };
    };
    

    Error on the playground

    If you want, you can infer it the other way, though, by leaving off the return type annotation on useAppState:

    export const useAppState = () => {
        const [notesData, setNotesData] = useState<INoteProps[]>([]);
    
        useEffect(() => {
            setNotesData([
                {something: "cool"} // <== Works
            ])
        }, []);
    
        return {
            notesData
        };
    };
    

    Playground example

    TypeScript will infer the return type as { notesData: INoteProps[]; }. Since TypeScript’s type system is structural (based on the shape of types) not nominal (based on the names of types), that’s the same as IAppStateProps.

    You may not want to do that, though, since an erroneous edit that accidentally changes the return type of the function wouldn’t be caught by TypeScript. In practice, I find inferring the return type is fine for really short, simple functions, but for anything beyond that I need the safety net of specifying what the return should be so edits accidentally changing it get caught early. Your mileage may vary. 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search