如何使用非 OOP 方法对 MobX 可观察对象进行类型注释?

发布于 2025-01-10 07:07:52 字数 581 浏览 1 评论 0原文

请考虑这个例子:

import { observable } from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = ???;

const obj1Observable: MyObjectObservable = observable(obj1); // I want to have compiler error here

function doStuff(obj: MyObjectObservable) {}

doStuff({ name: "Uldis", age: 35 }) // I want to have compiler error here because passed object is not an observable

MyObjectObservable 的类型应该如何定义?我希望拥有尽可能严格的类型,并且不想使用 OOP 方法,因为存在其他类型相关问题,例如方法使用的状态没有精确的子类型。

Please, consider this example:

import { observable } from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = ???;

const obj1Observable: MyObjectObservable = observable(obj1); // I want to have compiler error here

function doStuff(obj: MyObjectObservable) {}

doStuff({ name: "Uldis", age: 35 }) // I want to have compiler error here because passed object is not an observable

How should type for MyObjectObservable be defined? I want to have as strict types as possible and I don't want to use OOP approach because of other type related issues such as not having precise subtypes for the state that methods use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏了南城 2025-01-17 07:07:52

使用 observable 或 makeObservable 时,Typescript 中不应出现错误,

这是所有有效的代码:

import { makeAutoObservable, observable } from "mobx"

interface MyObject {
  name: string
  age: number
}

const obj1 = { name: "Uldis", age: 35 }

const make: MyObject = makeAutoObservable(obj1)
const obj1Observable: MyObject = observable(obj1)

function doStuff(obj: MyObject) {}

doStuff({ name: "Uldis", age: 35 })
doStuff(make)
doStuff(obj1Observable)

There should be no error in Typescript when using observable or makeObservable

This is all valid code:

import { makeAutoObservable, observable } from "mobx"

interface MyObject {
  name: string
  age: number
}

const obj1 = { name: "Uldis", age: 35 }

const make: MyObject = makeAutoObservable(obj1)
const obj1Observable: MyObject = observable(obj1)

function doStuff(obj: MyObject) {}

doStuff({ name: "Uldis", age: 35 })
doStuff(make)
doStuff(obj1Observable)

隐诗 2025-01-17 07:07:52

我看到两种可能的解决方案:

  1. 使用盒装 observable
import { observable, IObservableValue } from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = IObservableValue<MyObject>;

const obj1Observable: MyObjectObservable = observable.box(obj1);

obj1Observable.get(); // returns MyObject
  1. 添加您自己的品牌 Observable 类型,以避免使用额外的对象进行包装。
//customObservable.ts

import {observable as observableImpl} from 'mobx'

const mobx = Symbol('mobx');
export type Observable<T> = T & { [K in typeof mobx]: never };

export const observable = <T extends object>(obj: T): Observable<T> => {
  return observableImpl(obj) as Observable<T>;
};

import { observable, Observable } from "./customObservable";
import { observable as originalObservable} from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = Observable<MyObject>;

const obj1Observable: MyObjectObservable = observable(obj1);
const obj2Observable: MyObjectObservable = originalObservable(obj1); // compile-time error

obj1Observable.name; //string
obj1Observable.age;  //number

I see two possible solutions:

  1. Use boxed observable
import { observable, IObservableValue } from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = IObservableValue<MyObject>;

const obj1Observable: MyObjectObservable = observable.box(obj1);

obj1Observable.get(); // returns MyObject
  1. Add your own branded Observable type in order to avoid wrapping with an additional object.
//customObservable.ts

import {observable as observableImpl} from 'mobx'

const mobx = Symbol('mobx');
export type Observable<T> = T & { [K in typeof mobx]: never };

export const observable = <T extends object>(obj: T): Observable<T> => {
  return observableImpl(obj) as Observable<T>;
};

import { observable, Observable } from "./customObservable";
import { observable as originalObservable} from "mobx";

interface MyObject {
  name: string;
  age: number;
}

const obj1 = { namee: "Uldis", age: "35" };

type MyObjectObservable = Observable<MyObject>;

const obj1Observable: MyObjectObservable = observable(obj1);
const obj2Observable: MyObjectObservable = originalObservable(obj1); // compile-time error

obj1Observable.name; //string
obj1Observable.age;  //number
机场等船 2025-01-17 07:07:52

仔细研究后,我想出了这个解决方案:

import { makeObservable,IObservableValue } from "mobx"

type MyObservable=IObservableValue<{name:string}>

const obj = makeMyObservable({ name:'Johny' })
const obj2 = {name:'Johny'}

function makeMyObservable<T extends Record<string,any>>(val:T){

    return makeObservable(val) as unknown as IObservableValue<T>
}

function onlyMyObservable(val:MyObservable){
    return val
}

onlyMyObservable(obj)
onlyMyObservable(obj2) // error

TS 游乐场

After looking at this more closely I've came up with this solution:

import { makeObservable,IObservableValue } from "mobx"

type MyObservable=IObservableValue<{name:string}>

const obj = makeMyObservable({ name:'Johny' })
const obj2 = {name:'Johny'}

function makeMyObservable<T extends Record<string,any>>(val:T){

    return makeObservable(val) as unknown as IObservableValue<T>
}

function onlyMyObservable(val:MyObservable){
    return val
}

onlyMyObservable(obj)
onlyMyObservable(obj2) // error

TS Playground

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文