-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
"Stricter" TypeScript #274
Comments
Does it make sense for noImplicitAny to be rolled in as part of this stricter TypeScript? Or is there value keeping it separate? |
I'd like to hear feedback on that one -- would anyone want |
I think |
👍 |
It'd be nice to have a flag to tighten the type compatibility rules (e.g. #222) |
|
This is a great meta-issue. My preference is for all these features (including noImplicitAny) to be included in the default compilation (i.e. no flags). We could have a flag that people can use to relax the rules, for example --lenient or --dontCatchErrors (that's a joke, btw). A --strict flag might be confused with "use strict". |
that is what I thought when I first looked at the title |
Yeah it may be the case that we need to use a different term than 'strict' to minimize confusion but it's ultimately a small issue that's easy to change at any time before the feature goes into a final release. |
@NoelAbrahams - it'd need to be behind a flag to not break backward compatibility with code that's building against the current 1.0 compiler. Not that I want to start a woodshed about naming, but I 👍 that "strict" is too overloaded, especially in the JS world. |
It's too late to make I agree with the sentiment that |
👍
|
How about In all seriousness I think |
I also like |
|
Perhaps the important question here is not so much the name but the compatibility promise associated with the flag. Will it only enforce a certain set of restrictions forevermore or can new restrictions be added under the same flag in future? My personal preference would be to enable new restrictions by default under such a flag but provide opt-outs on a per-module basis that can be easily enabled to keep existing code compiling under new versions of tsc. The rationale being that it will improve the quality of the code in the TypeScript ecosystem as a whole. I'd like to see --noImplicitAny made the default but that would break the important feature that new users can convert existing JS code to TypeScript just by changing the file extension. |
|
@KamyarNazeri Is the error code from the compiler non-zero (e.g. |
The warning level for C# compiler is a zero-index value, 0 being the lowest (turns off emission of all warning messages) while higher numbers show more warnings: As mentioned by others, I too believe having levels of warnings could be extensible for future use |
The answer was on the page @KamyarNazeri mentioned for C#:
Since we want all of these to be |
Our general plan is to provide simpler flags (probably just |
Not sure if this has been mentioned before, but how about an option to restrict multiple uses of interface declarations? I've run into a case where I forgot that I had already used an interface name somewhere and in this case the 2 interfaces get merged - which I understand is useful - but in some cases it would be useful to be able to say that you want this interface to not collide with any other one, so in case another exists already, throw a compile error and let you know that you need to pick another name?
|
This is a tracking issue for other issue, all of which are in the category of changes to the type system rather than additional features or syntax. Please post suggestions for new syntax or features elsewhere. Thanks! |
perhaps this suggestion #185 could be included in the list |
Again, this is only for additional "rules", not new features or new syntax. |
Note #1740 as a potential additional error level, although it may be too much of the 'fork the language' case and there're better solutions if we do real 'this' typing in the core language. |
I think it would be really nice if I could ask the compiler to warn me when I do this: var data:Model = JSON.parse(json); Instead of "silently" assigning the value of type The compiler would stop complaining if I provided a type assertion. For example: var data:Model = <Model>JSON.parse(json); I like this because I am assuming responsibility for the type cast. If Thoughts? |
You can get the desired behavior by changing the return type of |
Since you're looking for motivating examples for disallowing function argument bivariance: we have code where we pass around constructor functions. These constructors accept an argument of an interface, but one of them incorrectly assumed it would get one specific concrete implementation of this interface instead. We expected this kind of thing to be caught but instead it was a runtime bug. |
It would be good to have ability to raise warning/error for all properties which don't have AccessibilityModifier like |
@markbook2 you can do that easily today with a regular expression( see below). Plus, this is a meta-bug, so you should probably file a new issue and reference this. |
@markbook2 @afrische TSLint has a rule for enforcing explicit visibility on class members / methods called |
👍 --noImplicitAny should be default, but obviously for backcompat reasons it can't be. But it should definitely be part of any '--strict' mode. |
Here is another motivating examples for disallowing function argument bivariance: In our typescript code base, we have an interface for classes having an export interface Eq {
equals(x: any): boolean;
} Because of function argument bivariance, classes can implement this interface "incorrectly", that is by narrowing the argument type class C implements Eq {
constructor(private c: number) {}
// I would like to get an error here, stating that the method signature in
// the Eq interface does not match the implementation given here.
// In OO-languages such as C# or Java, you get this error.
equals(that: C) {
return this.getNum() === that.getNum();
}
getNum() {
return this.c;
}
}
class D {
constructor(private d: number) {}
equals(that: D) {
return this.d === that.d;
}
} We now write a function that searches in an array of function findInArray(arr: Array<Eq>, x: Eq): number {
for (let i = 0; i < arr.length; i++) {
if (arr[i].equals(x)) {
return i;
}
}
return -1;
} Now it's rather easy to trigger an unexpected runtime error: const arr = [new C(1), new C(2)];
const i = findInArray(arr, new D(2));
console.log(i); The program now aborts with |
We have moved to a more piecemeal approach to such checks, e.g. control flow checks, strict this, strict null, etc.. feels like this issue is obsolete. @RyanCavanaugh any objections to closing it? |
Another case where bivariant arguments really hurt is the React and Redux world, where mismatches in React component props are one of the most frequent source of errors. Currently it's perfectly valid to have: interface MyComponentProps {
title: string;
}
export class MyComponent extends React.Component<MyComponentProps, void> {
// code that needs this.props.title
}
const MyComponentAlias: React.ComponentClass<{}> = MyComponent;
// use of MyComponentAlias blows up, as it doesn't require title, but title is needed for MyComponent The |
I would like a flag under which TypeScript would reject any program that it could not prove to be free of type errors at runtime. In addition to proving that a large class of bugs (type errors) are impossible, an AOT compiler (for servers) for "sound" typescript could erase the types at runtime for a perf gain. |
@DemiMarie what you're describing is not broadly possible given the constraints of our type system. As one example of many, we have no plausible way to prevent mutation after aliasing a structure with a less-specific type introducing an incorrect value into that structure, e.g. : const a = [1, 2, 3];
const b: Array<string | number> = a;
b[0] = 'oops';
console.log(a[0] + 1); // 'oops1' We've done a good job implementing almost everything in the OP so I'm going to close this due to a lack of usefulness of a meta-issue. Some good discussion happening at #9642 about how to get these stricter options on by default in places where it wouldn't be troublesome. |
This a meta-bug for tracking a set of things that we could address with a compiler flag that tightens certain aspects of TypeScript that users generally perceive as too loose.
Will add to this list as appropriate
return
statements in type-annotated functionsIssue a warning when generic type inference produces {} #360: Error when generic type inference produces ex nihilo- now a default{}
Contentious issues that have been mentioned:
Done!
Not happening:
Inherited types in callback functions #222: Function argument bivarianceNote: This is not a "fork the language" flag. The type system itself would be unchanged under this flag; it would simply change some operations from being allowed to being errors. For example, we would not change the order of overload resolution, or change the type of
null
, because that would have non-local effects and everyone would have to agree on whether or not the flag was on.The text was updated successfully, but these errors were encountered: