-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Need to cast string as string literal #25889
Comments
If you declares the return type of the lambda it works: interface Iperiod {
id: number | 'current';
name: string;
}
function usePeriods(periods: Iperiod[]) {
return periods;
}
usePeriods(['now', 'then'].map((name, index): Iperiod => {
if (name == 'now') {
return {
name,
id: 'current',
}
}
return {
name,
id: index,
}
})); I think is a duplicate. |
If I cast it like so it works:
, but damn, it feels dumb... |
There are actually a few reasons why you should ensure an object literal has a contextual type -- it helps avoid misspelling optional properties and gets you literal types. (See palantir/tslint#2581) |
@j-oliveras But the |
Created an issue to improve error reporting here: #26413 |
Could you please elaborate more on how this helps "avoid misspelling optional properties and gets you literal types"? Perhaps adding example, that says thousands words. |
The "it" in that sentence reverse to "has a contextual type", which comes from giving a type annotation to the object. That also prevents you from needing to cast string literals. interface I {
kind: "a" | "b",
optional?: number
}
declare function f(i: I): void;
// No contextual type
const i0 = { kind: "a" };
f(i0); // fails
const i1 = { kind: "a" as "a", optinal: 3 };
f(i1); // No compile error, but "optional" not specified as intended
f({ kind: "a", optional: 3 }); // Perfect!
f({ kind: "a", optinal: 3 }); // Compiler catches "optinal" spelling error |
I still have hard time understanding it. Or at least to me it is almost like f({ kind: "a", optinal: 3 });
f({ kind: "a" as "a", optinal: 3 }); I don't see why, if the string literal is in returned object is treated differently from one constructed in parameter. |
@Akxe the effective question is, let's say you write this const obj = { kind: "a" };
obj.kind = "b"; Is this code valid? When you write an expression, TS has to guess what the domain you intended was. We use the same inference for determining how it's legal to use the object both for read and for writes -- |
I get that point, but consider this interface I {
code: 'mapped',
name: string,
}
const a: I[] = ['a', 'b'].map(name => {
return {
code: 'mapped',
name,
}
}); Here the error is definitely unnecessary, as |
It is 2 years old... Any info on what it is waiting for? I saw there waiting for proposal, but how to make one, is there a template? |
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow. |
|
Note: |
Previously the Resource typing was awkward at best - asserting Resources to concrete types seamed like needles work that defied the point of having them defined as interfaces One potential solution was asserting string literal to string literal, but that felt backwards, example: "literal" as "literal" Someone in the Github thread[0] suggested asserting them in the following manner: "literal" as const - which is a bit better, but still misses the point Due to technical reasons the literal inferred type was string, rather than the literal itself. What seams to solve the problem is asserting the whole object to be a Resource. That also solves the problem with creeping import scope while at the same time setting up correct guards at compile time Last, but not least I think that the documentation on type assertion is misleading at best (couldn't find an example describing the mechanism and didn't feel like going through the source) - the mechanism is much more safe than described in the official docs, which cover the case of any -> T. Whereas in the more general case of T -> U assertion the overlap is checked (so that if I make a typo in the object an error is raised) [0] microsoft/TypeScript#25889
Previously the Resource typing was awkward at best - asserting Resources to concrete types seamed like needles work that defied the point of having them defined as interfaces One potential solution was asserting string literal to string literal, but that felt backwards, example: "literal" as "literal" Someone in the Github thread[0] suggested asserting them in the following manner: "literal" as const - which is a bit better, but still misses the point Due to technical reasons the literal inferred type was string, rather than the literal itself. What seams to solve the problem is asserting the whole object to be a Resource. That also solves the problem with creeping import scope while at the same time setting up correct guards at compile time Last, but not least I think that the documentation on type assertion is misleading at best (couldn't find an example describing the mechanism and didn't feel like going through the source) - the mechanism is much more safe than described in the official docs, which cover the case of any -> T. Whereas in the more general case of T -> U assertion the overlap is checked (so that if I make a typo in the object an error is raised) [0] microsoft/TypeScript#25889
Previously the Resource typing was awkward at best - asserting Resources to concrete types seamed like needles work that defied the point of having them defined as interfaces One potential solution was asserting string literal to string literal, but that felt backwards, example: "literal" as "literal" Someone in the Github thread[0] suggested asserting them in the following manner: "literal" as const - which is a bit better, but still misses the point Due to technical reasons the literal inferred type was string, rather than the literal itself. What seams to solve the problem is asserting the whole object to be a Resource. That also solves the problem with creeping import scope while at the same time setting up correct guards at compile time Last, but not least I think that the documentation on type assertion is misleading at best (couldn't find an example describing the mechanism and didn't feel like going through the source) - the mechanism is much more safe than described in the official docs, which cover the case of any -> T. Whereas in the more general case of T -> U assertion the overlap is checked (so that if I make a typo in the object an error is raised) [0] microsoft/TypeScript#25889
Was there a reason this was closed? I seemed to have missed it. |
TypeScript Version: 3.1.0-dev.201xxxxx
Search Terms:
string as string, cast string as string, cast string as string literal
I am sorry, I have no idea on how to search for it, enlighten me, if you know.
Code
Expected behavior:
It should work, as
id
can benumber | 'current'
.Actual behavior:
Error string is not assignable to 'current'.
Playground Link:
link
Related Issues:
No, but I suppose a few.
The text was updated successfully, but these errors were encountered: