Andrew
Andrew

Reputation: 795

Pass setState as a parameter Typescript

Consider the following:

// external file

export const someFunction = setState => {
    setState({ value: "some new string" })
} 

// component's file

import { someFunction } from "pathToFile"

interface TState {
    value: string
}

const [state, setState] = useState<TState>({ value: "some string" })

useEffect(() => {
   someFunction(setState)
}, [])

Is it possible to achieve that someFunction will accept only this particular setState function as а parameter? If so, how it could be done?

To be clear, I want:

someFunction(setState) // pass
someFunction(setAnotherState) // fail
someFunction(anotherFunctions) // fail
someFunction() // fail
someFunction(0) // fail
someFunction(true) // fail
someFunction({}) // fail

Upvotes: 2

Views: 8779

Answers (3)

bela53
bela53

Reputation: 3485

Basically, you are asking for a nominal type:

type NominalSetState = React.Dispatch<React.SetStateAction<TState>> &
  { readonly __brand_setState__: unique symbol }

const someFunction = (setState: NominalSetState) => {
    setState({ value: "some new string" })
}

function useNominalState(init: TState) {
    return useState<TState>(init) as [TState, NominalSetState]
}

const [state, setState] = useNominalState({ value: "some string" })
const [anotherState, setAnotherState] = useState<TState>({ value: "some string" })
Now, tests behave as desired:
someFunction(setState) // pass
someFunction(setAnotherState) // fail
someFunction() // fail
someFunction(0) // fail
someFunction(true) // fail
someFunction({}) // fail
someFunction((...arg: any[]) => any) // fail

Live code example

Upvotes: 3

Zain
Zain

Reputation: 98

You can achieve your goal by implementing the callback methods.

Example:

this.readStudentFile(anyFile, this.callback);

callback(isPass) {
 this.setState({ isPass: isPass });
}

readStudentFile(file: File, callback) {
 if(file) {
   callback(true);
 } else callback(false);
}

Upvotes: 2

Luke Storry
Luke Storry

Reputation: 6752

You could define a very specific parameter type to someFunction, which will give you the same pass/fails that you want.

Only allowing one particular object isn't what Typescript is really for - you are meant to guard by only allowing some interfaces, and anything with that same interface will be allowed.

Upvotes: 0

Related Questions