-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Make property access type checking less restictive #39065
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Duplicate of #38842 (and others). |
@MartinJohns Thank You once again for the hint, but this time it is not really a duplicate though the topic is similar. You mentioned a bug report but I know that the current behaviour of TypeScript is not a bug but a feature. I opened a feature request to make a different behaviour possible. It can be an optional feature realized by a compiler option, or a complete change of the behaviour. |
The "lack" of this feature is very much intentional; this pattern is not safe to use because object types aren't closed, so the existence of a value in some property slot is really not a solid indication that anything correct is happening. The See e.g. #37343 (comment) |
@RyanCavanaugh Maybe I went too far with my suggestion but isn't it okay to allow it at least in an |
@PetaSoft no. You could write something like this, for example, which is legal according to the type system but would crash at runtime: interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
function getSmallPet(): Fish | Bird {
const b = { swim: true, fly() { }, layEggs() { } };
return b;
}
let pet = getSmallPet();
// Each of these property accesses will cause an error
if (pet.swim) {
pet.swim();
} else if (pet.fly) {
pet.fly();
} |
@RyanCavanaugh Your example should be added to the TypeScript Handbuch (subsection Type Guards and Differentiating Types). It is a very good reason not to allow a property access in an |
No worries 🙂 |
@RyanCavanaugh In your example, why doesn't the type checker catch the run time error? It appears to know it's a boolean at the return type. This issue around property access seems like it has been requested a lot. I'm surprised there hasn't been a fix besides asking all devs to switch to using |
Search Terms
TypeScript 3.9, property access, type checking, union types
Suggestion
I want to propose a less restictive way of type checking for property access. To illustrate the new way of type checking, I want to cite the example which is mentioned in the TypeScript Handbook (section "Advanced Types", subsection Type Guards and Differentiating Types):
The property access
pet.swim
is not allowed because typeBird
does not have a propertyswim
. In Javascript these kinds of property access are allowed and ifpet
does not have that property the result value isundefined
.I think that a property access
pet.swim
should be allowed even if not all parts of the union type have that property. The type of the result would be() => void | undefined
. Theif(pet.swim)
type guard would eleminte theundefined
from the result type in the body of theif
statement, andpet.swim()
would be allowed, too. The same would be the case forif(pet.fly)
.This less restictive type checking does not cause any runtime errors, and more Javascript code can be ported to Typescript without any change.
I want to mention that of course a statement
pet.swim()
without a type guard would still cause a compile time error aspet.swim
is of type() => void | undefined
andundefined
is not callable.Going one step further, it can also make sense to allow property access even if the type of the object does not have a member with that property name:
Of cource, once again
x()
is not allowed asundefined
is not callable. These kinds of property access do not cause any runtime errors but the first design goal of TypeScript is probably too much affected if it would be allowed.At least, a compiler option would be helpful which allows such less restictive property accesses. Additionally, the compiler could emit warnings for such property accesses instead of errors.
I want to mention that the solution presented in the TypeScript Handbook does no longer work because of stricter type checks in
if
statements:One gets the error: "This condition will always return true since the function is always defined".
It can be fixed using the
in
operator:Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: