'Object is of type 'unknown' typescript generics
I have a simple function that takes a function as it's argument and returns a new function. I get Object is of type 'unknown'
when calling the returned function
const makeFunction = <T>(callback: (someParam: number, options: T) => any) => {
return (options: T) => {
const param = 4;
return callback(param, options)
}
}
Above code is okay for typescript but when I am calling function I get complaint
makeFunction((param, options) => {
const a = options.optionsValue //(parameter) options: unknown, Object is of type 'unknown'
})({optionsValue: 'some value'})
Solution 1:[1]
We need to think how TS can infer the type from this definition. TS can understand type from two places:
- explicit generic type set
- type of second argument of the function
In your use case you don't provide type in any of those places and this is the reason you get unknown
, because how TS can know what argument type you need. In order to give TS possibility to understand the type you can do or:
Set explicitly generic by:
makeFunction<YourType>((param, options) => {...))
Set type in callback function by for example defining one beforehand:
const f = (a: number, b: {a: string}) => b // here types are set
makeFunction(f)({a: 'some value'}) // makeFunction is able to infer the types by f
You can also do this inline by saying ((param: number, options: MyType))
Answer after comment if options
can be dynamic
I believe you want below behavior:
const makeFunction = <F extends (someParam: number, options: any) => any>(callback: F) => {
return (options: Parameters<F>[1]) => {
const param = 4;
return callback(param, options)
}
}
const f = (a: number, b: {a: string}) => b
makeFunction(f)({ a: 'a' })
const g = (a: number, b: {b: number}) => b
makeFunction(g)({b: 1})
We say few things:
F
is now function which extends from binary function, and we directly infer its typeParameters<F>[1]
is second argument type of given functionF
type
Solution 2:[2]
Since this is the first result you get when you google Object is of type 'unknown'
, I want to post my case. It might help future readers. This is not the answer to OP's question.
I got this error in the catch
block. After debugging for a while I came to know that starting typescript v4.0, catch clause variables have type unknown
instead of any
.
And according to docs:
unknown is safer than any because it reminds us that we need to perform some sort of type-checks before operating on our values.
My code looked something like this before v4.0:
try {
// try something exceptional here
} catch (error) {
console.log(error.message);
}
And to fix this error, I had to put an additional if
check on error
variable.
try {
// try something exceptional here
} catch (error) {
let errorMessage = "Failed to do something exceptional";
if (error instanceof Error) {
errorMessage = error.message;
}
console.log(errorMessage);
}
Solution 3:[3]
updating my tsconfig.json
with the following has worked for me:
"useUnknownInCatchVariables": false,
Update:
you need to put it like this under compilerOptions
"compilerOptions": {
"useUnknownInCatchVariables": false
}
Note: You need Typescript v4.4 or higher to be able to use this compiler option else you get a compiler error.
Solution 4:[4]
I got this issue in a try/catch
bumping the Typescript to version 4.4 and found in the documentation the explanation for that.
In resume they added the flag useUnknownInCatchVariables
that is true by default if strict
. It basically changes the type of the error in a catch
from any
to unknown
causing this issue.
So in order to bump to 4.4 you have some options:
try {
...
} catch(e) {
console.log((e as Error).message)
}
or:
try {
...
} catch(e) {
if (e instanceof Error) {
console.log(e.message)
}
}
or in your tsconfig.json
you can explicitly set the flag to false
:
{
"compilerOptions": {
"strict": true,
"useUnknownInCatchVariables": false
}
}
Solution 5:[5]
You can use casting: (err as Error)
I like the if
statement solution, but this also works:
catch (error) {
let msg = (error as Error).message;
}
Solution 6:[6]
Issue with TS 4.0 explained here: https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/#unknown-on-catch
All of the other answers didn't work for me but using the isAxiosError
worked just fine:
} catch (error) {
if (axios.isAxiosError(error)) {
const errResp = error.response;
// Handle your error type safe here
} else {
// Handle the unknown
}
}
No Object is of type 'unknown'.ts(2571)
error anymore.
Solution 7:[7]
Create an interface for options or use any as type,
makeFunction((param, options: any) => {
const a = options.optionsValue;
})({optionsValue: 'some value'});
Typescript takes options type as {} which causes issue during compilation.
Solution 8:[8]
Add a type to the calling function like this:
function(): Observable<any>
to avoid it from returnig unknown
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | |
Solution 5 | Dmitri R117 |
Solution 6 | |
Solution 7 | aran |
Solution 8 | mkamal |