Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to "extract" the type of TypeScript interface property?

Let's suppose there's a typing file for library X which includes some interfaces.

interface I1 {
    x: any;
}
    
interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

In order to work with this library I need pass around an object that is of exactly the same type as I2.y. I can of course create identical interface in my source files:

interface MyInterface {
    a: I1,
    b: I1,
    c: I1
}

let myVar: MyInterface;

but then I get the burden of keeping it up to date with the one from library, moreover it can be very large and result in lot of code duplication.

Therefore, is there any way to "extract" the type of this specific property of the interface? Something similar to let myVar: typeof I2.y (which doesn't work and results in "Cannot find name I2" error).


Edit: after playing a bit in TS Playground I noticed that following code achieves exactly what I want to:

declare var x: I2;
let y: typeof x.y;

However it requires a redundant variable x to be declared. I am looking for a way to achieve this without that declaration.

like image 374
Kuba Jagoda Avatar asked Mar 30 '16 14:03

Kuba Jagoda


People also ask

How do you check TypeScript type?

Use the typeof operator to check the type of a variable in TypeScript, e.g. if (typeof myVar === 'string') {} . The typeof operator returns a string that indicates the type of the value and can be used as a type guard in TypeScript.

Is type of interface TypeScript?

TypeScript Interface Type TypeScript allows you to specifically type an object using an interface that can be reused by multiple objects. To create an interface, use the interface keyword followed by the interface name and the typed object.

Where are types and interfaces TypeScript stored?

The hybrid approach uses a global and component or model-based approach. In that way, you can store types and interfaces in a global folder that are common across the project. Also, you can store specific types and interfaces that are strictly related to a specific component, controller or service.

What is record type in TypeScript?

TypeScript Records are a great way to ensure consistency when trying to implement more complex types of data. They enforce key values, and allow you to create custom interfaces for the values. The TypeScript Record type was implemented in TypeScript 2.1, and takes the form Record<K, T> .


4 Answers

It wasn't possible before but luckily it is now, since TypeScript version 2.1. It has been released on the 7th of December 2016 and it introduces indexed access types also called lookup types.

The syntax looks exactly like element access but written in place of types. So in your case:

interface I1 {
    x: any;
}

interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

let myVar: I2['y'];  // indexed access type

Now myVar has type of I2.y.

Check it out in TypeScript Playground.

like image 168
Michał Miszczyszyn Avatar answered Oct 03 '22 03:10

Michał Miszczyszyn


To expand on the accepted answer, you can also assign the type using the type keyword and use it in other places.

// Some obscure library
interface A {
  prop: {
    name: string;
    age: number;
  }
}

// Your helper type
type A_Prop = A['prop']

// Usage
const myThing: A_prop = { name: 'June', age: 29 };
like image 23
Ben Winding Avatar answered Oct 03 '22 04:10

Ben Winding


keyof Colors will return a list of all keys "white" | "black". When this list of keys gets passed to the Colors interface, the type will be all the values of the given keys, "#fff" | #000.

interface Colors {
  white: "#fff"
  black: "#000"
}

type ColorValues = Colors[keyof Colors]
// ColorValues = "#fff" | "#000"
like image 30
Gabriel Petersson Avatar answered Oct 03 '22 03:10

Gabriel Petersson


Just an example of extracting a literal type from the union object type:

type Config = {
    key: "start_time",
    value: number,
} | {
    key: "currency",
    value: string,
}

export type ConfigKey = Config["key"];
// "start_time"|"currency"

like image 21
James Bond Avatar answered Oct 03 '22 04:10

James Bond