这是场景。
我有一个接口,表示通用var aud = document.getElementById("myAudio");
aud.onplay = function() {
alert("The audio has started to play");
};
的元数据(假设我们正在谈论Angular Material的Field
实例),它由名称和类型组成,该类型和类型是常见输入类型的列表
MatFormField
某些export type FieldType = 'string' | 'number' | 'date' | 'datetime' | 'select';
export interface FieldMetadata {
readonly type: FieldType;
name: string;
}
仅适合那些元数据,而其他Field
则需要附加信息,因此需要接口扩展。
然后,我定义了一个联合类型,因此我可以根据“类型”字段获得正确的类型提示。
// Specific interface for select field
export interface SelectFieldInterface extends FieldMetadata {
readonly type: 'select';
options: string[];
}
// All other fields which doesn't need additional info
export interface GenericFieldInterface extends FieldMetadata {
readonly type: Exclude<FieldType, 'select'>;
}
export type Field = GenericFieldInterface | SelectFieldInterface;
// Understands it's a GenericFieldInterface
const genericField1: Field = {
type: 'number',
name: ''
};
const genericField2: Field = {
type: 'number',
name: '',
option: [] // <---- Type Error, unexpected 'options'
};
// Understands it's a SelectFieldInterface
const selectField1: Field = {
type: 'select',
name: '',
options: []
};
const selectField2: Field = {
type: 'select',
name: '',
// <----- Type Error, expected 'options'
};
这里一切都按预期进行(但是,如果您知道更好的管理方式,请分享)。
当我想以这种抽象为基础时,就会出现问题。
让我们说,应该在这种联合类型的顶部构建一个新模型,以保持区别。 我希望可以得到类似的结果。
export interface Model extends Field {
additionalProperty: string;
}
在TypeScript中 BUT 这是不可行的,您不能扩展联合类型。
我通过定义一个接受所有Field
类型的所有属性的中间“超类型”来部分解决了这个问题。
我必须在特定实现上省略类型属性,否则会因接受的类型值冲突而出现问题。
export type ExtendedField = FieldMetadata &
Partial<Omit<GenericFieldInterface & SelectFieldInterface, 'type'>>;
但是这样我就失去了两件事。
首先是区分各种实现方式。
const genericField: Model = {
type: 'number',
name: '',
additionalProperty: '',
option: [] // <---- Doesn't fire Type Error for 'option' property, it should
};
const selectField: Model = {
type: 'select',
name: '',
additionalProperty: '',
// <---- Doesn't fire Type Error for missing 'option' property, it should
};
第二个是Field
和Model
签名之间的兼容性:我不能在签名要求Model
的地方使用Field
。
当然,我知道它们是兼容的,但是编译器不兼容,因此我不得不将Model
强制转换为Field
。
function someFn(field: Field) {}
const selectField: Model = {
type: 'select',
name: '',
additionalProperty: '',
option: []
};
someFn(selectField) <------ Type Error
someFn(selectField as Field) <------ Works with casting
关于如何更好地表达这些矛盾的任何想法?我试图研究条件类型,但是我不明白它们是否对我有用...
答案 0 :(得分:1)
最简单的解决方案是将类型别名与交集一起使用,以添加所需的额外属性。只要这些类型仅用于类型检查对象文字,而不必由类实现,则它们应该都能正常工作:
CREATE PROCEDURE [dbo].[proc_SaveAccessRequest]
(
@TmpAR TmpAccessRequest READONLY,
@IsUAMSRequest bit,
@RequestID int OUTPUT
)
AS
BEGIN
Insert into tblRequests
(
RequesterID
,RequestType
,NextApprover
,RequestStatus
,Delegation
,CreatedOn
,CreatedBy
,[Description]
,IsSepecialRequest
,DelegationDetailID
,IsActive
,IsDeleted
,ModifiedOn
)
SELECT
RequesterID
,RequestType
,NextApprover
,RequestStatus
,Delegation
,CreatedOn
,CreatedBy
,Description
,IsSepecialRequest
,DelegationDetailID
,IsActive
,IsDeleted
,ModifiedOn
FROM @TmpAR
WHERE NOT EXISTS ( SELECT 1
FROM tblRequests i
INNER JOIN @TmpAR o
ON i.RequesterID = o.RequesterID
AND i.RequestType = o.RequestType
AND i.NextApprover = o.NextApprover)
SELECT @RequestID = SCOPE_IDENTITY()
SELECT @RequestID
END