Description
Right now we are merging the types of a package with the types needed for actions and components. It’d be great to to merge somehow the packages types.
For example, imagine this package:
import { Package } from "frontity/types";
interface MyPackage extends Package {
state: {
myPackage: {
someState: string;
};
};
actions: {
myPackage: {
someAction: Action<MyPackage>;
};
};
}
export default MyPackage;
If any of your actions or components need state.router.link
then you need to add it to MyPackage
as an optional:
import { Package } from "frontity/types";
import Router from "@frontity/router/types";
interface MyPackage extends Package {
state: {
router?: Router["state"]["router"]; // <- here
myPackage: {
someState: string;
};
};
actions: {
myPackage: {
someAction: Action<MyPackage>;
};
};
}
export default MyPackage;
But these manual merges are:
- Ugly. You have to do them manually.
- They get verbose if you need to add multiple things like state, actions and libraries.
- Unnecessary for the
MyPackage
type when you use it to type your package insrc/index.js
. I’d say they are even bad because you have optional types that are not really optional. - Unnecessary when you import this type in other packages. Because this types from other packages doesn’t belong to it. They are only there because they are used internally in some action or component.
Possible solution
Initial proposed solution (click to open)
I propose to use two different types in the types.ts
file, one exclusively for the package, and the other a merge with the external packages for actions and components.
import { Package } from "frontity/types";
import Router from "@frontity/router/types";
interface MyPackage extends Package {
state: {
myPackage: {
someState: string;
};
};
actions: {
myPackage: {
someAction: Action<Packages>;
};
};
}
export default MyPackage;
export type Packages = Router & MyPackage;
I think it’s a cleaner approach, although it means people need to understand this a bit better because they need to use these to types in different places.
- They have to remember to use
Packages
in theirAction
andDerived
.
someAction: Action<Packages>;
someDerived: Derived<Packages>;
- They have to remember to import
MyPackage
in thesrc/index.ts
file:
import MyPackage from "../types";
const myPackage: MyPackage = {
state: {
myPackage: {
someState: ”some state”
}
},
actions: {
myPackage: {
someAction: ({ state }) => {
// Can access state.router.link.
}
}
}
}
export default myPackage;
- They have to remember to use
Packages
for their React components.
import { Connect } from "frontity/types";
import { Packages } from "../../types";
const Comp: React.FC<Connect<Packages>> = ({ state }) => {
// Can access state.router.link.
};
Same for useConnect
hook:
import { useConnect } from "frontity";
import { Packages } from "../../types";
const Comp: React.FC = () => {
const { state } = useConnect<Packages>();
// Can access state.router.link.
};
External packages will keep using the default import of types:
import MyPackage from "my-package/types";
But this time it will only contain the types of MyPackage and nothing else.
Maybe instead of Packages
we can call it Types
or just Frontity
(because it is the whole Frontity for this package).
@david, is it possible to do the merge of the types with a Merge
helper like this:
import { Package, Merge } from "frontity/types";
import Router from "@frontity/router/types";
import Source from "@frontity/source/types";
export type Packages = Merge<Router, Source MyPackage>;
Any thoughts? Feedback?