Package Exports
- @sanity-typed/types
- @sanity-typed/types/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@sanity-typed/types) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@sanity-typed/types
Typed Sanity Documents with zero schema changes!
Install
npm install @sanity-typed/types sanity
Usage
Use defineConfig
, defineType
, defineField
, and defineArrayMember
from this library exactly as you would from sanity's own exports. Then, you can InferSchemaValues
to have the typescript types!
// import { defineArrayMember, defineConfig, defineField, defineType } from "sanity";
import {
defineArrayMember,
defineConfig,
defineField,
defineType,
} from "@sanity-typed/types";
import type { InferSchemaValues } from "@sanity-typed/types";
// Corresponding example: https://www.sanity.io/docs/schema-field-types#e5642a3e8506
// No changes using defineArrayMember, defineField, and defineArrayMember https://www.sanity.io/docs/schema-field-types
const product = defineType({
name: "product",
type: "document",
title: "Product",
fields: [
defineField({
name: "productName",
type: "string",
title: "Product name",
}),
defineField({
name: "tags",
type: "array",
title: "Tags for item",
of: [
defineArrayMember({
type: "object",
name: "tag",
fields: [
{ type: "string", name: "label" },
{ type: "string", name: "value" },
],
}),
],
}),
],
});
// No changes using defineConfig https://www.sanity.io/docs/config-api-reference
const config = defineConfig({
// ...
schema: {
types: [
product,
// ...
],
},
});
export default config;
// This is where the magic happens!
type Values = InferSchemaValues<typeof config>;
// Import Product type into your application!
export type Product = Extract<Values, { _type: "product" }>;
/**
* Product === {
* _createdAt: string;
* _id: string;
* _rev: string;
* _type: "product";
* _updatedAt: string;
* productName?: string;
* tags?: ({
* label?: string;
* value: string;
* })[];
* };
**/
Named/Aliased Types
const foo = defineType({
name: "foo",
type: "document",
fields: [
defineField({
name: "bar",
type: "bar",
}),
],
});
const bar = defineType({
name: "bar",
type: "object",
fields: [
defineField({
name: "baz",
type: "boolean",
}),
],
});
const config = defineConfig({
// ...
schema: {
types: [
foo,
bar,
// ...
],
},
});
export default config;
type Values = InferSchemaValues<typeof config>;
export type Foo = Extract<Values, { _type: "foo" }>;
/**
* Foo === {
* _createdAt: string;
* _id: string;
* _rev: string;
* _type: "foo";
* _updatedAt: string;
* bar?: {
* _type: "bar";
* } & {
* baz?: boolean;
* };
* };
**/
Plugin Types
// import { definePlugin } from "sanity";
import { definePlugin } from "@sanity-typed/types";
const foo = defineType({
name: "foo",
type: "document",
fields: [
defineField({
name: "bar",
type: "bar",
}),
],
});
// No changes using definePlugin https://www.sanity.io/docs/developing-plugins
const barPlugin = definePlugin({
name: "plugin",
schema: {
types: [
defineType({
name: "bar",
type: "object",
fields: [
defineField({
name: "baz",
type: "boolean",
}),
],
}),
],
},
});
const config = defineConfig({
// ...
schema: {
types: [
foo,
// ...
],
},
plugins: [barPlugin()],
});
export default config;
type Values = InferSchemaValues<typeof config>;
export type Foo = Extract<Values, { _type: "foo" }>;
/**
* Foo === {
* _createdAt: string;
* _id: string;
* _rev: string;
* _type: "foo";
* _updatedAt: string;
* bar?: {
* _type: "bar";
* } & {
* baz?: boolean;
* };
* };
**/
Goals
Typescript was an after-the-fact concern with sanity, since the rise of typescript happened after sanity took off. The define*
methods are a good start, but they only help restrict the schema, not type the document types. There's been attempts, namely sanity-codegen
and @sanity-typed/schema-builder
, but they take the approach of creating a new way of building schemas. The drop-in replacement approach allows for zero migration cost.
The long term goal is to deprecate the monorepo altogether. Building this seperately was to move quickly and these features should be in sanity directly (and is likely one of their internal goals). The idea is to introduce these changes iteratively into sanity itself while removing them from this library, until it's reduced to simply passing through the define*
methods directly, and will then be deprecated.
This shouldn't deter you from using it! Under the hood, it's passing all the inputs to sanity's native define*
methods, so you shouldn't have any runtime differences. With all the typings being attempting to make their way into sanity, you should keep all the benefits of just importing the define*
methods and noticing no differences.