-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Can't use indexed/mapped type signature in interfaces? #13573
Comments
It looks like this is a solution: type Thing6 = Readonly<Partial<Record<Names, string>>> & { extra?: number }; However, I'm still curious if there is a better way. |
Personally, I would not like allowing to add extra properties on {type aliases|interfaces} having indexed definition, and not following this indexed definition constraint (in your case, your extra property is of type I often use such type definition (with For instance :
HOWEVER, if I disagree on your post statement to be able to "append" extra properties on indexed interfaces, I totally agree about the idea that it seems cumbersome to me to have the possibility to use I typically don't know why I'm not able to simplify my interface above like this :
I would still love to be able to declare Mapped Types in interfaces as it would open the doors to more complex constraints, particularly allowing me to specify common generics at the indexed definition level, and more precise type at the field level. For instance, let's consider my
Today, if I use |
+1 Hope we can use 'in' operator in index signature while declaring interfaces not only types. We really need a mapped index sometimes. The inconsistency between interface and type looks confusing. |
Is there any movement on this issue? It seems to be something that is extremely useful, and quite a common use case. If there is no plan to support something like:
then is there a suggested alternative pattern that achieves the same goal -- namely being able to define an object shape where the key may be any of a list of acceptable values? |
@aaroncraig10e I was also looking for something like that. For now this interface TT {
unit: string,
decimals: number,
prefix: string,
postfix: string,
}
type MySymbols = 'BTC' | 'CZK' | 'ETH' | 'EUR' | 'LTC'
type S1 = {
[P in MySymbols]: TT
}
interface S2 {
format: (value: number, currency: MySymbols) => string
}
type S = S1 & S2 // intersection here
const SYMBOLS: S = {
BTC: { unit: 'BTC', decimals: 5, prefix: '', postfix: '' },
CZK: { unit: 'CZK', decimals: 2, prefix: '', postfix: ',-' },
ETH: { unit: 'ETH', decimals: 4, prefix: 'Ξ', postfix: '' },
EUR: { unit: 'EUR', decimals: 2, prefix: '€', postfix: '' },
LTC: { unit: 'LTC', decimals: 3, prefix: '', postfix: '' },
format(value, currency) {
const c = this[currency] // this gets inferred as any and not of type TT
return c.prefix + value.toFixed(c.decimals) + c.postfix
},
} |
@ackvf use |
cause it would have been a breaking change otherwise. |
I was also surprised when I discovered I cannot create mapped interfaces directly. The TS handbook says:
I am happy this no longer seems to be the case |
hope can use when type is string symbol number |
@mpawelski If you don't mind me asking, how did you do that? As far as I know, interfaces cannot extend from type declarations in TypeScript (TS2312). |
@jameswilddev It was introduced in typescript 2.2.0. You will in fact get error TS2312: An interface may only extend a class or another interface in previous versions if you try to compile my example from previous post. works fine: You can read more details in Allow deriving from object and intersection types PR |
@mpawelski Aha, think it's just that I'm overbending the type system a bit. On 3.1.6, something closer to your example works: type SingleKeyValueOf<T> = {
[key in "A" | "B"]: string
}
interface X<T> extends SingleKeyValueOf<T> { } However, this doesn't: type SingleKeyValueOf<T> = {
[key in keyof T]: string
}
interface X<T> extends SingleKeyValueOf<T> { } Thanks. |
any updates on this? |
Tracking at #26797 |
Note that this isn't completely a duplicate of #26797, since that one would not have really supported mapped types (index signatures don't give you a handle on the elements in the set of keys). This issue seems to be the canonical one for "why can't we add extra properties next to mapped types" which isn't quite the same as "why can't we have arbitrary index signatures". |
TypeScript Version: 2.1.5
What I'd like to do is effectively extend from a record type and then add a few more custom properties. Since type aliases cannot by extended, I tried solving the problem with an indexed type signature in the interface. Unfortunately, this doesn't compile. I also can't add extra properties to a mapped type, so it seems I may be stuck. Is there a way around this problem?
Code
Expected behavior:
I would expect all of these to compile.
Actual behavior:
Thing1
andThing2
fail to compile due to the indexed type signature.Thing5
fails to compile due to the extra property.The text was updated successfully, but these errors were encountered: