Repository: motion-canvas/motion-canvas
File: packages/core/src/Project.ts (TypeScript)

Code before:
    return this.variables;
  }

  public readonly name: string;
  public readonly audio = new AudioManager();
  public readonly logger = new Logger();
  public readonly background: string | false;
  public readonly creationStack: string;
  public playbackState = createSignal(PlaybackState.Paused);
  private readonly renderLookup: Record<number, Callback> = {};
  private _resolutionScale = 1;
  private _colorSpace: CanvasColorSpace = 'srgb';
  private _fileType: CanvasOutputMimeType = 'image/png';
  private _quality = 1;
  private _speed = 1;
  private framesPerSeconds = 30;
  private previousScene: Scene | null = null;
  private canvas: HTMLCanvasElement | null = null;
  private context: CanvasRenderingContext2D | null = null;
  private buffer = document.createElement('canvas');
  private bufferContext: CanvasRenderingContext2D | null = null;
  private previousBuffer = document.createElement('canvas');
  private previousBufferContext: CanvasRenderingContext2D | null = null;
  private exportCounter = 0;
  private size = Vector2.zero;
  private variables: {[key: string]: any} = {};

  /**
   * @deprecated Use {@link makeProject} instead.
   *
   * @param config - The project configuration.
   */
  public constructor(config: ProjectConfig);
  public constructor(
    name: string,
    meta: Meta<ProjectMetadata>,
    config: ProjectConfig,
  );
  public constructor(
    name: string | ProjectConfig,
    meta?: Meta<ProjectMetadata>,
    config?: ProjectConfig,
  ) {
    const {
      scenes,
      audio,
      audioOffset,
      canvas,
      size = ProjectSize.FullHD,
      background = false,
      variables = {},

Review comment (suggestion):
I would suggest that we use a type like `unknown` here instead of `any` -- `any` turns off the type system, and since we return this to user-code that means we can pollute the typing in that code, too. The way using `unknown` would require users to ensure that the project variables are the types they are expecting (or they can cast them if they so choose, but then they're making the choice).

Code after:

  public readonly name: string;
  public readonly audio = new AudioManager();
  public readonly logger = new Logger();
  public readonly background: string | false;
  public readonly creationStack: string;
  public playbackState = createSignal(PlaybackState.Paused);
  private readonly renderLookup: Record<number, Callback> = {};
  private _resolutionScale = 1;
  private _colorSpace: CanvasColorSpace = 'srgb';
  private _fileType: CanvasOutputMimeType = 'image/png';
  private _quality = 1;
  private _speed = 1;
  private framesPerSeconds = 30;
  private previousScene: Scene | null = null;
  private canvas: HTMLCanvasElement | null = null;
  private context: CanvasRenderingContext2D | null = null;
  private buffer = document.createElement('canvas');
  private bufferContext: CanvasRenderingContext2D | null = null;
  private previousBuffer = document.createElement('canvas');
  private previousBufferContext: CanvasRenderingContext2D | null = null;
  private exportCounter = 0;
  private size = Vector2.zero;
  private variables: Record<string, unknown> = {};

  /**
   * @deprecated Use {@link makeProject} instead.
   *
   * @param config - The project configuration.
   */
  public constructor(config: ProjectConfig);
  public constructor(
    name: string,
    meta: Meta<ProjectMetadata>,
    config: ProjectConfig,
  );
  public constructor(
    name: string | ProjectConfig,
    meta?: Meta<ProjectMetadata>,
    config?: ProjectConfig,
  ) {
    const {
      scenes,
      audio,
      audioOffset,
      canvas,
      size = ProjectSize.FullHD,
      background = false,
      variables = {},
    } = typeof name === 'string' ? config! : name;