I have the following function, which could receive an unknown value:
function formatReason(detail: unknown): string {
if (detail
&& detail instanceof Object
&& detail.constructor.name === 'Object'
&& detail.hasOwnProperty('description')
&& typeof detail['description'] === 'number'
) {
const output = detail['description'];
return output;
}
return '';
}
The detail
parameter could be any value. If it's an object with a description
property of type string, the function should return that property value, otherwise empty string.
First, do you recommend using any
or unknown
for the detail
parameter?
Second, no matter what I do, the type for output
ends up to be any
. How can I make sure it is string
?
New unknown top typeunknown is the type-safe counterpart of any . Anything is assignable to unknown , but unknown isn't assignable to anything but itself and any without a type assertion or a control flow based narrowing.
Use a user-defined type guard to check if a value with unknown type contains a property in TypeScript. The user-defined type guard consists of a function that checks if the specific property is contained in the object and returns a predicate. Copied!
To check if a property exists in an object in TypeScript: Mark the specific property as optional in the object's type. Use a type guard to check if the property exists in the object. If accessing the property in the object does not return a value of undefined , it exists in the object.
unknown and any are 2 special types that can hold any value. unknown is recommended over any because it provides safer typing — you have to use type assertion or narrow to a specific type if you want to perform operations on unknown .
The "Object is of type unknown" error occurs when we try to access a property on a value that has a type of unknown. To solve the error, use a type guard to narrow down the type of the object before accessing a property, e.g. if (err instanceof Error) {}.
Use a user-defined type guard to check if a value with unknown type contains a property in TypeScript. The user-defined type guard consists of a function that checks if the specific property is contained in the object and returns a predicate. We used a user-defined type guard to check if an object contains the name and age properties.
With the unknown type, we have to first check the type that's currently stored in the variable before we get TypeScript support. The type is used when there's no way to know what the value stores in advance, so you can only access properties and methods on it by using type guards.
You can use the conventional way, by asking your bankers to check it. Just forward the property details, and they will call up their panel bank valuer and get a verbal indication. However, some bankers might be reluctant to check if you haven’t booked a property as they want a genuine client.
Edit: got corrected by Neon. The typeguard was not sufficient enough. I updated the example to explicitly assert an unknown
value instead of an implicit any
.
I'd recommend using unknown
as it is the type-safe variant of any
, that being said you probably want to use a type guard to assert the unknown value. This has the effect that the description
property you're looking for is actually being asserted as a string
and not as an any
.
The typeguard (see the playground to see what IDescription
is):
public hasDescription(obj: unknown): obj is IDescription { return (obj as IDescription).description !== undefined && typeof (obj as IDescription).description === "string"; }
Using it in the codebase will result in an if-statement with some benefits.
if (this.hasDescription(detail)) { // In this if-block the TypeScript compiler actually resolved the unknown type to the type described in the guard. console.log(detail.description); }
Here's a playground for you to see how that works (note how only 123
is being outputted to the console).
An example implementation for your specific problem:
function formatReason(detail: unknown): string { if (this.hasDescription(detail) { return detail.description; } return ''; }
There isn't a great way to write this code until this suggestion is implemented. In the meantime, it's up to you whether you prefer any
or unknown
(with some casts if you are using noImplicitAny
, as I'd generally recommend). I wouldn't worry about the type of the output
local variable because you've declared the return type of the function as string
anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With