#typescript #typescript-typings
Вопрос:
Я делаю здесь что-то не так или это специально?
Я хотел бы иметь возможность написать что-то подобное.
type MyType = {
greeting: string;
value?: { valueType: string; value?: string };
};
function generate(name: string, input?: Partial<MyType['value']>): MyType {
return {
greeting: `Hello, ${name}`,
value: input?.valueType ? input : undefined,
};
}
Как вы можете видеть, я использую тернарный оператор для проверки правильности моего input
объекта, но TypeScript жалуется и выдает ошибку:
Тип «неопределенный» не может быть присвоен типу «строка». (2322)
Ответ №1:
Сужение машинописного текста сработало должным образом, если вы переопределите свойства своего объекта. Рабочий пример :
Код :
type MyType = {
greeting: string;
value?: { valueType: string; value?: string };
};
function generate(name: string, input?: MyType['value']): MyType {
return {
greeting: `Hello, ${name}`,
value: input?.valueType ? {
valueType: input.valueType,
value: input.value
} : undefined,
};
}
Комментарии:
1. Это изменило бы семантику и не позволило бы передавать
input
пропущенноеvalueType
свойство, в то время как код OP допускает это. Я просто упоминаю об этом в комментарии — не совсем ясно, действительно ли OP нужно передавать объекты безvalueType
в функцию или нет.2. Я также хотел бы иметь возможность вызывать функцию следующим образом:
generate('Jógvan', { value: 'without a type' });
3. Теперь я лучше понимаю, каковы ваши намерения. Я отредактировал свой пост, сохранив возможность использовать подобный объект :
{ value: 'obj with no valueType' }
4. То, что вы предоставили, — это именно то, чего я хотел избежать, но я вижу, что это то, что нужно. Но вот кто-то показывает 3 строками, почему то, что я хочу, не поддерживается: github.com/microsoft/TypeScript/issues/…
Ответ №2:
Чтобы понять, что пошло не так, сначала давайте проверим тип в обратном положении. Это value
свойство имеет следующий тип (как и ожидалось):
{ valueType: string; value?: string | undefined; } | undefined;
Давайте также проверим, что input?.valueType ? input : undefined
дает нам:
Partial<{
valueType: string;
value?: string | undefined;
}> | undefined
И в этом заключается проблема: вы сказали компилятору, что ожидаете valueType
, что он будет иметь тип string
, но то, что вы на самом деле пытались ему назначить string | undefined
(очевидно, потому Partial
что помощник сделал это valueType
свойство необязательным).
Это Partial<T> | undefined
выводится, поскольку вы также сообщили компилятору, что generate
функция принимает Partial<MyType['value']>
в качестве второго параметра. Итак, что вы можете с этим поделать? Без изменения семантики единственным вариантом звучания является также сделать valueType
необязательным:
type MyType = {
greeting: string;
value?: {
valueType?: string;
value?: string;
};
};
function generate(name: string, input?: Partial<MyType['value']>): MyType {
const value = input?.valueType ? input : undefined;
return { greeting: `Hello, ${name}`, value }; //OK
}
Вероятно, это не то, что вы ищете. Однако для достижения вашей цели вам потребуется дополнительная цепочка, которая будет действовать как защита типа, так и «сопоставление» типа, о котором вы сказали компилятору Partial
, чтобы удалить модификаторы. Это возможно с помощью определяемого пользователем типа защиты, который может выглядеть следующим образом:
const withType = (val: Partial<MyType["value"]>) : val is Exclude<MyType["value"], undefined> => !!val?.valueType;
function generate(name: string, input?: Partial<MyType['value']>): MyType {
const value = withType(input) ? input : undefined;
return { greeting: `Hello, ${name}`, value }; //OK
}