Pesquisa de site

typescript - Distinguir entre objetos comuns e tipos de classe


Como posso distinguir um tipo de objeto simples de um tipo de classe?

class Foo {
  constructor(public a: number) {}
}

declare let obj: {a: number}
declare let inst: Foo

// Either one would be fine.
type IsPlainObject<T> = ???
type IsClassType<T> = ???

Isso é necessário se você quiser usar "tipos mapeados" em objetos simples, mas nunca em tipos de classe.

edição: Os tipos de classe parecem ser idênticos às interfaces em muitos (na maioria? todos?) casos:

class Foo { a?: number }
class Bar { a?: number }

type A = Foo extends Bar ? 1 : 0  // => 1
type B = Bar extends Foo ? 1 : 0  // => 1

type Obj = { a?: number }

type C = Foo extends Obj ? 1 : 0  // => 1
type D = Obj extends Foo ? 1 : 0  // => 1

Link do playground

Questões relevantes

  • https://github.com/Microsoft/TypeScript/issues/29063
  • https://github.com/Microsoft/TypeScript/issues/5303#issuecomment-148894708

Resposta #1

Isso parece funcionar para mim:

type PlainObject<T> = T extends Record<keyof T, T[keyof T]> ? T : never;