Static CMS
Star StaticJsCMS/static-cms on GitHubSponsor
v4.3.0DocsExamplesDemoCommunitySponsor

Typescript

Static CMS provides first class support for Typescript when using the Bundling option.

Configuration

When using Typescript it is recommended to store your CMS configuration in a typescript file instead of a yaml file to take full advantage of the typings available.

import type { Config } from '@staticcms/core';

export const config: Config = {
  ...
}

Custom Widgets

When providing your own widgets, you can extend the Config type with your custom widget types to provide proper typing in your config. All custom widget types should extend the BaseField interface.

import type { Config, BaseField } from '@staticcms/core';

export interface HtmlField extends BaseField {
  widget: 'html'
  default: string;
}

export interface CustomField extends BaseField {
  widget: 'custom'
  default: number[];
  some_other_prop: string;
}

export const config: Config<HtmlField | CustomField> = {
  ...
}

Widgets

When providing types for custom widgets you need to know the datatype your widget works with and the definition of its Field. The examples below assumes the field interface for the widget is in the config.ts file in the parent directory.

Control Component

Control widgets take the WidgetControlProps interface as their props.

import type { FC } from 'react';
import type { WidgetControlProps } from '@staticcms/core';
import type { HtmlField } from '../config';

const EditorControl: FC<WidgetControlProps<string, HtmlField>> = ({
  field, // Typed as a HtmlField
  value, // Typed as string | null | undefined
  onChange, // Typed to accept string | null | undefined
}) => {
  ...
};

Preview Component

Control widgets take the WidgetPreviewProps interface as their props.

import type { FC } from 'react';
import type { WidgetPreviewProps } from '@staticcms/core';
import type { HtmlField } from '../config';

const EditorPreview: FC<WidgetPreviewProps<string, HtmlField>> = ({
  field, // Typed as a HtmlField
  value, // Typed as string | null | undefined
}) => {
  ...
};

Preview Templates

When providing types for custom preview templates you need to know the datatype of your collection (or file) that the template is represents. Preview templates take the TemplatePreviewProps interface as their props.

import { useEffect, useMemo, useState } from 'react';

import type { FC } from 'react';
import type { TemplatePreviewProps } from '@staticcms/core';

interface PostPreviewData {
  body: string;
  date: string;
  title: string;
  image?: string;
  slug: string;
  tags?: string[];
}

const PostPreview: FC<TemplatePreviewProps<PostPreviewData>> = ({
  entry, // Typed as PostPreviewData
  widgetFor, // Typed to accept only the keys of PostPreviewData (body, date, title, image, slug, tags)
  collection,
  fields
}) => {
  const dateString = useMemo(() => entry.data.date, [entry.data.date]);

  const imageField = useMemo(() =>
    fields.find((field) => field.name === 'image'),
    [fields]
  );
  const image = useMediaAsset(entry.data.image ?? '', collection, imageField, entry);

  return (
    <div>
      <h1>{entry.data.title}</h1>
      <div>{entry.data.date}</div>
      <img title={title} src={image} />
      <div>{(entry.data.tags ?? []).join(', ')}</div>
      <div>{widgetFor('body')}</div>
    </div>
  );
};