any
TypeRepresents all possible TS types and JS values.
any
is a top type (universal supertype) of the type system
any
type is too permissive
any
type, it's easy to pass type check, but fail at runtimeunknown
TypeType-safe counterpart of any
type.
Similar to the any
type, but is safer because it’s not legal to do anything with an unknown
value.
let unknownValue: unknown; unknownValue = 10; unknownValue = 'height'; if (typeof unknownValue == 'string') { const unknownKey = unknownValue.toUpperCase(); // Do something with unknownKey } else if (typeof unknownValue == 'number') { // Do something else when it is a number type }
With unknown
if you do not check the type, the linter
will show a type error
, because you are trying to use a method in an object whose type you don't know for sure, which can cause errors in execution time.
unknown
type is only assignable to the any
type and unknown
type.
Anything can be typed to unknown
, but unknown
type is not assignable to anything but itself and any
without a type assertion or a control flow based narrowing of type.
Also means no operations are permitted on an unknown
type without first asserting or narrowing to a more specific type.
We can narrow type using typeof
, instanceof
, or custom type guard operators.
See
Control Flow Based Type Analysis
Section
function unknownNarrowing(value: unknown): string { if (typeof value === "string") { // here, the value is string return `${value}`; } if (value instanceof Number) { // here, the value is Number // Number(value) would return NaN return +value; } return String(value); }
// type checking every element in value is number function isValueStringInArray(value: unknown): value is string[] { return ( Array.isArray(value) && value.every(el => typeof el === "string") ); } const unknownValue: unknown = ["hi", "bye", "this"]; if (isValueStringInArray(unknownValue)) { // if every element in value is a string, log the whole thing out console.log(unknownValue); }
unknown
Considered cheating the type system to make two incompatible types compatible
Below example takes mockType
object and cases it as unknown
unknown
type object to ArbitraryOverrideType
to force the compiler to understand mockType
as as ArbitraryOverrideType
const mockType = ({ id: 1, random_attribute: "something", uncompliant_attribute: "not compliant" } as unknown) as ArbitraryOverrideType
Below is an inversify test for mockedService
jest.fn()
After mocking the methods, we cast the service as a whole to an unknown
type
const mockedService = { getById: jest.fn(), getByIds: jest.fn(), } as unknown; // force-casted here container .bind<SomeService>(ServiceTypes.SomeService) .toConstantValue(mockedService as ISomeOtherService);