HomeToolsAbout

Any and Unknown

any Type

Represents all possible TS types and JS values.

any is a top type (universal supertype) of the type system

any type is too permissive

  • Using any type, it's easy to pass type check, but fail at runtime

unknown Type

Type-safe counterpart of any type.

This is similar to the any type, but is safer because it’s not legal to do anything with an unknown value

  • You have to check its type first even after it is typed to it
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.

Type Checking (Narrowing)

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); }

Custom Type Guard

// 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); }

Force Casting using unknown

Considered cheating the type system to make two incompatible types compatible

Below example takes mockType object and cases it as unknown

  • Then, it casts the 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

  • In the test, we do not want to call the entire service, so we're mocking the service methods using 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);
AboutContact