Typescript не проверяет типы при использовании spread-оператора

Никак не могу разобраться, почему не работает проверка типов в следующем примере:

interface Props {
    readonly value: string;
}

const Component = ({ value }: Props) => {
    return <div>{value}</div>;
};

const otherProps = {
  id: 'test',
}

const a = <Component {...otherProps} value='test' />

Ожидаю, что ts будет ругаться, так как свойство id не существует в типе Props.


Ответы (1 шт):

Автор решения: Qwertiy

А можно как-то изменить код, чтобы проверка заработала?

Можно, но тебе не понравится: песочница

import React from 'react'

interface Props {
    readonly value: string;
}

const Component = <P extends Props>({ value }: { [key in keyof P]: key extends keyof Props ? P[key] : never }) => {
    return <div>{value}</div>;
};

const otherProps = {
    id: 'test', 
}

const a = <Component value='test' />
const b = <Component {...otherProps} /> // Property 'value' is missing in type '{ id: string; }' but required in type '{ readonly value: string; }'
const c = <Component {...otherProps} value='test' /> // Type '{ value: "test"; id: string; }' is not assignable to type '{ value: "test"; id: never; }'

При желании можно вынести хэлперный тип, но компонент всё равно должен быть generic'омЖ песочница

import React from 'react'

interface Props {
    readonly value: string;
}

type Strict<P, B, R = { [key in keyof P]: key extends keyof B ? P[key] : never }> = R

const Component = <P extends Props>({ value }: Strict<P, Props>) => {
    return <div>{value}</div>;
};

const otherProps = {
    id: 'test', 
}

const a = <Component value='test' />
const b = <Component {...otherProps} />
const c = <Component {...otherProps} value='test' />

Я сделал R пораметром дженерика чтобы иметь более красивую ошибку несоответствия типов, хотя такая запись и позволяет натворить какую-то дичь передав третий параметр явно.

→ Ссылка