Description
TypeScript Version: Version 2.7.0-dev.20171112
I would like to restrict the input to a function to objects that can be serialised, and I've got it working OK for type
s, but not for classes or interfaces: I'm told they don't have an index signature.
This is related to issue #1897.
The motivation is that the firefox webextension storage API will only serialise certain objects.
A small example:
Code
declare namespace browser.storage {
// Non-firefox implementations don't accept all these types
type StorageValue =
string |
number |
boolean |
// ...
StorageArray |
StorageMap |
StorageSet |
StorageObject;
// The Index signature makes casting to/from classes or interfaces a pain.
// Custom types are OK.
interface StorageObject {
[key: string]: StorageValue;
}
// These have to be interfaces rather than types to avoid a circular
// definition of StorageValue
interface StorageArray extends Array<StorageValue> {}
interface StorageMap extends Map<StorageValue,StorageValue> {}
interface StorageSet extends Set<StorageValue> {}
type StorageArea = {
set: (keys: StorageObject) => Promise<void>,
// ...
};
const sync: StorageArea;
}
type A = {
prop: string[];
}
interface B {
prop: string[];
}
class C {
constructor(public prop: string[]) {}
}
interface D extends browser.storage.StorageObject {
prop: string[];
}
const a: A = { prop: [] }
const b: B = { prop: [] }
const c = new C([])
const d: D = { prop: [] }
browser.storage.sync.set({ a }) // Works
browser.storage.sync.set({ b }) // Fails: no index signature
browser.storage.sync.set({ c }) // Fails: no index signature
browser.storage.sync.set({ d }) // Works
a.foo = 1 // Property 'foo' does not exist on type 'A'.
b.foo = 1 // Property 'foo' does not exist on type 'B'.
c.foo = 1 // Property 'foo' does not exist on type 'C'.
d.foo = 1 // No error (this is bad)
Errors:
example.ts(51,26): error TS2345: Argument of type '{ b: B; }' is not assignable to parameter of type 'StorageObject'.
Property 'b' is incompatible with index signature.
Type 'B' is not assignable to type 'StorageValue'.
Type 'B' is not assignable to type 'StorageObject'.
Index signature is missing in type 'B'.
example.ts(52,26): error TS2345: Argument of type '{ c: C; }' is not assignable to parameter of type 'StorageObject'.
Property 'c' is incompatible with index signature.
Type 'C' is not assignable to type 'StorageValue'.
Type 'C' is not assignable to type 'StorageObject'.
Index signature is missing in type 'C'.
example.ts(55,3): error TS2339: Property 'foo' does not exist on type 'A'.
example.ts(56,3): error TS2339: Property 'foo' does not exist on type 'B'.
example.ts(57,3): error TS2339: Property 'foo' does not exist on type 'C'.
In addition to this issue, I'd also like to express that instances of a class can be stored (you can't store objects with functions, but prototypes and constructors are ignored).
This bug is tracked on the web-ext-types repo (that I maintain) at https://github.com/kelseasy/web-ext-types/pull/38#issuecomment-343855598
Expected behavior:
Some feature exists to suit the above use case.
Actual behavior:
See example
Thanks for yo time