Jackie Anxis
Jackie Anxis

Reputation: 65

Some problems with the optional properties in typescript interface

I am a beginner in TypeScript, when I learn the Interface in TypeScript, I find some features that I don't understand.

I have try the codes followed in the playground: https://www.typescriptlang.org/play/

interface LabelledValue {
  size?: number;
}
function printLabel(labelledObj: LabelledValue) {
}
let myObj = {label: "Size 10 Object"};
printLabel(myObj); // error: Type '{ label: string; }' has no properties in common with type 'LabelledValue'.

However, when I set the size property in myObj, it works, no error occurs.

interface LabelledValue {
  size?: number;
}
function printLabel(labelledObj: LabelledValue) {
}
let myObj = {label: "Size 10 Object", size: 10};
printLabel(myObj);

As I know, size is just an optional property, why is it necessary, and when I don't set it, there is an error occured.

Upvotes: 1

Views: 1348

Answers (2)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

This behavior was introduced by this PR a while ago. The basic idea is that if a type has only optional properties it is considered 'weak'. This is a problem as any other type would be compatible with a weak type. Given this issue it was decided that at least one property must match with the weak type for assignment to be allowed. From the PR:

A weak type is one which has only optional properties and is not empty. Because these types are assignable from anything except types with matching non-assignable properties, they are very weakly typechecked. The simple fix here is to require that a type is only assignable to a weak type if they are not completely disjoint.

Upvotes: 2

SoWhat
SoWhat

Reputation: 5622

Its got nothing to do with the parameter being optional. Atleast one of the properties must match. Since size is the only property present in the interface, it must be present in the object you're trying to cast. If I add another property and populate it instead of size, it works

interface LabelledValue {
    size?: number;
    something: string;
}
function printLabel(labelledObj: LabelledValue) {
}
let myObj = {label: "Size 10 Object", something: "Hello"};
printLabel(myObj);

See https://som.sh/fd6f6

Upvotes: 0

Related Questions