Skip to content

theroyalwhee0/commonprops

CommonProps

npm version npm downloads License

TypeScript utility types for extracting common properties from multiple types.

Overview

This module provides two main approaches to finding common properties:

  • Strict mode: Properties must have exactly matching types
  • Upcast mode: Primitive literals can be upcast to their base types (e.g., 'hello' → string)

Installation

npm install @theroyalwhee0/commonprops

Usage

interface Cat { name: string; type: 'cat'; active: true; }
interface Dog { name: string; type: 'dog'; active: false; }

// Strict: only exact matches
type StrictCommon = CommonStrictProps<[Cat, Dog]>; // { name: string }

// Upcast: literals become primitives  
type UpcastCommon = CommonUpcastProps<[Cat, Dog]>; // { name: string; type: string; active: boolean }

API

Full API documentation is available at:

  • Latest Release - Documentation for the most recent stable release
  • Unreleased - Documentation for the current main branch (may include unreleased features)

Main Types

  • CommonStrictProps<T[]> - Find common properties with strict type matching
  • CommonUpcastProps<T[]> - Find common properties with primitive literal upcasting

Helper Types

  • IsUpcastable<T> - Check if a type can be upcast to its primitive base
  • GetUpcastable<T> - Get the primitive base type for a given type
  • CommonStrictPairs<T, U> - Two-type strict comparison
  • CommonUpcastPairs<T, U> - Two-type upcast comparison

Behavior Details

Property Exclusion vs Inclusion

Properties are completely excluded when they cannot be unified:

interface A { name: string; type: 'cat'; }
interface B { name: string; type: 'dog'; }

type Strict = CommonStrictProps<[A, B]>;
// Result: { name: string }
// 'type' property is excluded entirely (not present in result type)

Type Selection Priority

When types can be unified, more general types are preferred:

// Example: string vs 'literal' 
type Mixed = CommonUpcastPairs<{prop: string}, {prop: 'literal'}>;
// Result: {prop: string} - chooses the more general type

// Multi-step example:
interface Cat { type: 'cat' }
interface Dog { type: 'dog' }  
interface Bird { type: 'bird' }

type Step1 = CommonUpcastPairs<Cat, Dog>;    // {type: string}
type Step2 = CommonUpcastPairs<Step1, Bird>; // {type: string} (maintains generality)

Recursive Processing

Multi-type functions process types left-to-right, maintaining type generality:

type Result = CommonUpcastProps<[Cat, Dog, Bird]>;
// Equivalent to: CommonUpcastPairs<CommonUpcastPairs<Cat, Dog>, Bird>

Links

Development Notes

  • This project uses a whitelist approach to .gitignore

License & Copyright

This project is licensed under the Apache License 2.0 - see the LICENSE.txt file for details.

Copyright 2025 Adam Mill