4
votes
interface SomeType {
  a: string;
  b?: string;
}

const foo: SomeType = {
  a: 'hello',
  b: 'there'
};

const bar: SomeType = {
  a: 'hello'
};
bar.b = 'there';

// Error on this line
const str: string = foo.b;

// These lines have no error
const str2: string = foo.b ? foo.b : '';
const str3: string = foo.b!;
const str4: string = bar.b;

In the example above, we have 2 flavors creating an object of SomeType, which has an optional property b. When declaring foo, we are setting the value of b when the object is created. For bar, we are setting a value of b after the object has been created.

When creating the first string, str, there is an error:

Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2322)

This error is mitigated with the approaches for str2 and str3. I understand that in these examples, we are either checking the value of foo.b or asserting that we know foo.b has a value.

I'm not understanding why the error does not appear when str4 is created. Why is TypeScript able to detect that bar.b is not undefined but it wasn't able to detect the same thing for foo.b? What is it about the way we are setting the property that results in this error?

(TypeScript Version 3.8.2)

2
It looks like typescript can tell that bar.b is either a string or undefined, - GrandFleet

2 Answers

0
votes

Removing SomeType from the line const foo: SomeType = ... will make the code work.

interface SomeType {
  a: string;
  b?: string;
}

const foo = {
  a: 'hello',
  b: 'there'
};

const bar: SomeType = {
  a: 'hello'
};
bar.b = 'there';

// No more error on this line
const str: string = foo.b;

// These lines have no error
const str2: string = foo.b ? foo.b : '';
const str3: string = foo.b!;
const str4: string = bar.b;

In the original code, you are casting object { a:..., b:...} to an interface. In this case SomeType:

const foo: SomeType = {
  a: 'hello',
  b: 'there'
};

Simplest example of this would be, if you modify last line for str4 to add cast, you will produce same error:

const str4: string = (bar as SomeType).b; // error, because of the cast
0
votes

There are chances that you see this error in almost all of your components if you enable the strictTemplates in the angularCompilerOptions in tsconfig.json file.

enter image description here

From Angular 9, we have this new feature called strictTemplates.

  "angularCompilerOptions":{
    "strictTemplates": true
  }

It is indeed a good feature, however, if you don't have enough time to fix all these errors, you can just set this to false, for example, when you have an important release.

There is a good blog post that explains this more.