Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Type 'ISimpleType<string>' is not assignable to type 'string'#2238

Answeredbythegedge
OnkelTem asked this question inQ&A
Discussion options

So this simple code:

typeFoo={foo:string}constMyModelFoo=types.model<Foo>('Foo',{foo:types.string,})

triggers the following error:

Type 'ISimpleType<string>' is not assignable to type 'string'

What I do wrong? This looks like a bug.

You must be logged in to vote

The typing here is probably a bit confusing, but I'd recommend using your type for instances, not the model itself:

type Foo = {  foo: string}const MyModelFoo = types.model('Foo', {  foo: types.string,})const fooInstance: Foo = MyModelFoo.create({ foo: "test" })

The problem in your example is that the generic argument fortypes.model describes the structure of the properties and not the instance.{ foo: types.string } does not match{ foo: string }, hence the error you're seeing. Itwould match{ foo: "abc" }, which would actually be the same as{ foo: types.optional(types.string, "abc") }.

In general I'd recommend always letting TypeScript derive the generic arguments fortypes.…

Replies: 1 comment 8 replies

Comment options

thegedge
Jan 7, 2025
Collaborator

The typing here is probably a bit confusing, but I'd recommend using your type for instances, not the model itself:

type Foo = {  foo: string}const MyModelFoo = types.model('Foo', {  foo: types.string,})const fooInstance: Foo = MyModelFoo.create({ foo: "test" })

The problem in your example is that the generic argument fortypes.model describes the structure of the properties and not the instance.{ foo: types.string } does not match{ foo: string }, hence the error you're seeing. Itwould match{ foo: "abc" }, which would actually be the same as{ foo: types.optional(types.string, "abc") }.

In general I'd recommend always letting TypeScript derive the generic arguments fortypes.model :)

You must be logged in to vote
8 replies
@thegedge
Comment options

thegedgeJan 7, 2025
Collaborator

@OnkelTem everything looks to be working as expected in the TS playground links you provided. In the first one, there are no type errors as expected, sinceFooDerived["foo"] andFoo["foo"] are bothstrings. In the second there are type errors becauseFoo["foo"] is anumber andFooDerived["foo"] is astring.

I'm also seeing intellisense when creating a model, and also when referencing properties on a created model:

CleanShot 2025-01-07 at 13 52 50@2x

CleanShot 2025-01-07 at 13 52 41@2x

Do you have a more complete example where things aren't working?

@OnkelTem
Comment options

Intellisense works for an existing model, while I speak about creatingthe model itself.

Instead we're given with a TypeScript API, whereFoo is already defined and we create a model for it, so we type:

t.model('Foo', {...

and get nothing, because model isn't typed.

In the second there are type errors because Foo["foo"] is a number and FooDerived["foo"] is a string.

Yeah, but that's a result of an investigation and not what is displayed in the error message.

@thegedge
Comment options

thegedgeJan 7, 2025
Collaborator

Oh, I think I understand what you're asking now. You type

t.model('Foo',{

And then ask for intellisense to show you options. There aren't meant to be options there by default, but you happen to already have an existing interface and want to have MST adhere to that. I don't think there's a natural solution that MST can give you (maybe you have some suggestions?), but I can see two options that you could use without any changes to MST:

Usesatisfies

The type of a properties blob is pretty complicated, so I don't think you can easily adapt some arbitrary interface to it. If you happen to only be mapping keys to primitive values, you could probably do something similar to what we do internally (which MST could expose):

/**
* Unmaps syntax property declarations to a map of { propName: IType }
*
*@hidden
*/
exporttypeModelPropertiesDeclarationToProperties<TextendsModelPropertiesDeclaration>=
Textends{[k:string]:IAnyType}// optimization to reduce nesting
?T
:{
[KinkeyofT]:T[K]extendsIAnyType// keep IAnyType check on the top to reduce nesting
?T[K]
:T[K]extendsstring
?IType<string|undefined,string,string>
:T[K]extendsnumber
?IType<number|undefined,number,number>
:T[K]extendsboolean
?IType<boolean|undefined,boolean,boolean>
:T[K]extendsDate
?IType<number|Date|undefined,number,Date>
:never
}

Alternatively, if you only care about the keys, you could do something like this:

types.model("Foo",{}satisfiesRecord<keyofFoo,any>)

That's kind of gross though, so maybe this would be better:

import{types,IType}from"mobx-state-tree";typeFoo={foo:string;};constMyModelFoo=types.model("Foo",{foo:types.string,})satisfiesIType<any,Foo,any>;

Adjust your type assertions

If your interface is meant to match an instance/snapshot of a model, which I'm guessing it is given your playground links, I would recommend something close to what you had in TS playground:

import{types,SnapshotOut}from"mobx-state-tree";typeFoo={foo:number;};constMyModelFoo=types.model("Foo",{foo:types.string,});typeFooDerived=SnapshotOut<typeofMyModelFoo>typeTest<TextendsFoo>="yes";type_=Test<FooDerived>

That will give you something a little more meaningful in the error message at the cost of having to write these out for every model:

CleanShot 2025-01-07 at 15 11 43@2x

@OnkelTem
Comment options

I see, Jason! Many thanks :)

As for the ideas - yeah, I've got one:#2239 :)

@coolsoftwaretyler
Comment options

@thegedge really nailed it here, but I understand where you're coming from,@OnkelTem.

I'll add that I've seen thesatisfies approach work pretty well. I did a bit of consulting with a team that used it for a similar use case as yours, and I thought it was clever.

I'll read through#2239 and think it over. But as things stand, that's my best recommendation for you with MST as-is.

Answer selected bycoolsoftwaretyler
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
3 participants
@OnkelTem@thegedge@coolsoftwaretyler

[8]ページ先頭

©2009-2025 Movatter.jp