7

Is there a way in TypeScript to transform a type into an interface?

I already read this QA here on StackOverflow, and don't think it fits well with the description I give in this Question.

A quick example of a scenario where a Product is defined as type from a third-party TypeScript library.

// ProductFragmentOne is used to highlight the possibility of composition(unions, etc)
type Product = ProductFragmentOne & { sku: string };

To integrate that Product into our own system, it is already possible by extending(union) a type as in the following example:

export type ProductSchema = Product & { 
  name: string;
}

My question is:

  • Is there a way for our ProductSchema to be defined as an interface? Is that even possible?
# Example of how the code may look
export interface ProductSchema{ 
  name: string;
  //Do the magic to add Product properties here
}

Update: The reason for this approach is purely a preference for interface over type. It makes existing code keep its style, regardless of third party library adopted.

Thanks.

P.M
  • 2,880
  • 3
  • 43
  • 53
  • 1
    No, probably not. You can only make an `interface` from a `type` if it is already an object type (or intersection of object types) whose keys are statically known. Since `Product` is a union it does not satisfy the restriction. Of course `{ ... }` is not actual code, so this isn't a [mcve] that I can be sure about one way or the other. Why do you want an `interface` anyway? Do you *need* it for some reason? Or is it just preference? – jcalz Oct 02 '20 at 01:25
  • 1
    There's not really any reason for this since almost everything that you can do with interfaces can also be done with types. If Product is a union type then there is probably a reason for it, and even if you could define a base interface that both types of Product objects extend, there will likely be cases where you can create an object which is assignable to the base interface but not assignable to Product because it is based on conflicting parts of the two Product types. You don't want that. You don't want to do this. – Linda Paiste Oct 02 '20 at 01:52
  • I updated the question with more clarifications on two previous comments. People do write code differently, and the style used in one project should not influence the way dependent projects are written(structured). – P.M Oct 02 '20 at 03:29

1 Answers1

13

To solve this problem, I used an answer found on a completely unrelated question: Is it "Possible to extend types in Typescript?".

In fact, since TypeScript 2.2 -- It is possible for an interface to extend a type.

There is an extensive thread on the difference between interface and type on this StackOverflow thread: TypeScript: Interfaces vs Types

export interface ProductSchema extends Product{ 
  name: string;
}

// Where the Product is a type similar to
type Product = { SKU: string }

The "magic trick" I was looking for was indeed that extends operator(or keyword). There is an additional example on TypeScript playground based on this same approach as well

P.M
  • 2,880
  • 3
  • 43
  • 53
  • 1
    Anyone have a trick to also not have to declare a separate type definition, so that we can do `export interface ProductSchema extends typeof ProductObj{ name: string; }` – chrismarx Oct 22 '21 at 14:56
  • 2
    It should perhaps be pointed out that: »An interface can only extend an object type or intersection of object types with statically known members.ts(2312)« so that the following construct unfortunately does not work: `const ctype: Readonly = ["a", "b"] as const; type ttype = typeof ctype[number]; interface xyz extends ttype {…}` – Denis Giffeler Jan 06 '22 at 17:13