json
"tslint": "5.10.0",
"tslint-config-airbnb": "5.9.2",
"tslint-react": "3.6.0",
json
"typescript": "2.9.1",
I have the following configuration:
json
{
"rules": {
"align": [true, "elements", "members", "parameters", "statements"],
"interface-name" : [true, "never-prefix"],
"max-line-length": {"options": {"limit": 999}},
"no-console": false,
"no-inferrable-types": true,
"no-string-literal": true,
"object-curly-spacing": [true, "never"],
"object-literal-sort-keys": false,
"ordered-imports": false,
"space-before-function-paren": false,
"trailing-comma": [true, {
"singleline": "never",
"multiline": {
"objects": "always",
"arrays": "always",
"functions": "never",
"typeLiterals": "ignore"
}
}],
"typedef": [true, "call-signature", "parameter"],
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"]
},
"extends": [
"tslint:recommended",
"tslint-eslint-rules",
"tslint-config-airbnb",
"tslint-react"
]
}
And this Typescript code:
javascript
private static readonly DEVICE_UID: string = 'device_uid';
private static readonly DEVICE_PLATFORM = 'browser';
Why I'm not getting error in the first declaration?
No errors throwed.
Rule no-inferrable-types should throw an error.
@sandrocsimas There is a bit of difference between those two member declarations. DEVICE_UID will have a type of string while DEVICE_PLATFORM will have the type 'browser'.
The rule makes a special exception for the readonly modifier (by ignoring declarations with that modifier). But since the static keyword is also there, I think there should be some sort of warning about unnecessary widening of the type. Maybe there's a use-case I'm not thinking of. @ajafff ?
@aervin, I didn't understood why DEVICE_PLATFORM will have the type 'browser'? Isn't this a string?
In my mind these three examples should result in a error:
javascript
private static readonly DEVICE_UID: string = 'device_uid';
private static DEVICE_UID: string = 'device_uid';
private DEVICE_UID: string = 'device_uid';
In both cases you're defining the type string and setting a string value. This is redundant.
Why they have different behavior?
@sandrocsimas I agree it's a bit confusing. See this tslint issue and this TS issue for some background.
OK @aervin, I understood that is some strange behavior in Typescript. In my case, even without the type definition, I don't get an error (the opposite of what happen in the examples provided in the issues you've mentioned). This should be due to the static definition.
It seems like this:
// case #1
// DEVICE_UID can only be one thing: 'device_uid'
class A {
private static readonly DEVICE_UID = 'device_uid';
}
should always be preferred over this:
// case #2
// same as above, but explicitly tells TS not to narrow the type of DEVICE_UID
class B {
private static readonly DEVICE_UID: string = 'device_uid';
}
I agree that tslint should warn about the typedef in the case #2 example. However, I think it's preferable that the TS compiler point out case #2's problem. Because of the string typedef, a class member could do something silly like this:
switch(B.DEVICE_UID) {
case 'random_string':
// ... this will never be executed
}
EDIT: TS playground example
@sandrocsimas @aervin is there an actual issue in the code here? seems like it was all a big misunderstanding.
@giladgray, I was expecting an error, but @aervin said this is the expected behavior since I'm using readonly. I think the issue can be closed, but it would be nice if you analyze the behavior when readonly is used with static.
馃憤
readonly and static mean different things and can be combined elegantly to make a singleton constant
@giladgray for the record, I think TS should warn about this issue, not tslint.
agreed