56

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.

1
  • 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. Commented May 16, 2018 at 19:30

3 Answers 3

18

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.

Sign up to request clarification or add additional context in comments.

Comments

4

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

Comments

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

1 Comment

It's creative but a little messy, in general, a solution that doesn't require changing the classes is usually preferred.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.