41

Suppose I have the following code:

interface A {
    a: number;
}

interface B extends A {
    b: number;
}

const b: B = {a: 1, b: 5};
const a: A = b as A;

Now the variable a has type A, but it still contains b inside of it. Sometimes it is undesirable - I'd like to be sure that, if I have a variable of type A, it has the exact fields of type A. I was wondering, whether TypeScript has some kind of a "hard cast" which would remove any unneeded fields when converting between types.

SalysBruoga
  • 875
  • 1
  • 9
  • 21
  • TypeScript doesn't do *any* casting or conversion. Also it's structurally typed, so *"this thing isn't X because it has extra fields"* doesn't really make sense. – jonrsharpe May 16 '18 at 19:30

3 Answers3

13

There is no casting in TypeScript because that's not how TypeScript works. TS is a type layer on top of JS. When you assign a type in TS you don't set a type, you annotate that the given expression is of a certain type. When the TS code is transpiled to JS, all type information is stripped.

Or in other words: the type system is JS, with TS you just announce that a variable is of a certain type. More often than never it happens that you assign the wrong type at design time and get suprised during debug that the variable has a completely different type than expected.

If you want to be sure that a property is removed from an object, you need to go the JS way (and - if necessary - annotate the result with TS). Check this Q&A to see how to remove properties from an object.

Sefe
  • 13,731
  • 5
  • 42
  • 55
1

Typescript won't do this for you, because it's not his job.

interface A {
    a: number;
}

interface B extends A {
    b: number;
}

const b: B = {a: 1, b: 5};
const a: A = b as A; // you want to remove a.b

Using the ellipsis

const {a, ...otherProperties} = b; // extract the property `a` and keep the other properties in `otherProperties`

Or just delete "a", but avoid deleting, it's imperative and TS won't understand it, it is also slower to handle deleted properties for the vm

delete a.b;

Or using lodash, you can pick the properties you want

const a = _.pick(b, ["a"]); // pick only a

Or omit a property still using lodash

const a = _.pick(b, ["b"]); // omit b

Example

Flavien Volken
  • 19,196
  • 12
  • 100
  • 133
0

I originally didn't plan on answering, but the reason I chose to answer because I feel like deleting the data in the original object might not always be a good idea.

Instead I think it's better to create a new variable and copy the data (without the unneeded properties) to the new variable.

I my case, I wanted to cast my register form into login information (email & password) and other information (on how the found the website).

The following solution is fairly easy to use (in various situations) and easily expandible.

export class HowFoundWas {
  howFoundWas: foundWasMedia;
  referrerdBy?: string;
  otherSocialMedia?: string;
  referredBySocialMedia?: string;
  otherMedia?: string;

  constructor(howFoundWas: any) {
    [
      "howFoundWas",
      "referrerdBy",
      "otherSocialMedia",
      "referredBySocialMedia",
      "otherMedia",
    ].forEach((prop) => {
      this[prop] = howFoundWas[prop];
    });
  }
}
Ruben Szekér
  • 1,065
  • 1
  • 10
  • 21