New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a good way to accurately identify the cause of an error in a union type? #58109
Comments
There usually is more error elaboration than that. Without a full code example, it’s impossible to say why it’s not diving into |
type CreateApi = {
alarmType: number
alarmLevel: number
alarmPerson: { personName: string, concatInfo: string, deleted: boolean }[]
alarmTarget: ({
deleted: boolean
managementDep: number
associatedProjectId: number
} | {
deleted: boolean
managementDep: number
dataSetId: number
})[]
}
type EditApi = {
id: number
alarmType: number
alarmLevel: number
alarmPerson: { personName: string, concatInfo: string, deleted: boolean, id?: number }[]
alarmTarget: ({
deleted: boolean
managementDep: number
associatedProjectId: number
id?: number
} | {
deleted: boolean
managementDep: number
tableName: string
id?: number
})[]
}
type Detail = {
id: number
alarmTarget: {id: number, managementDep: number, dataSetId?: number, associatedProjectId?: number, deleted: boolean}[]
alarmPerson: {id: number, personName: string, concatInfo: string, deleted: boolean}[]
alarmType: number
alarmLevel: number
createTime: number
}
type AlarmPersonItem = Detail['alarmPerson'][0]
type AlarmTargetItem = Detail['alarmTarget'][0]
type AlarmPersonRecord = Pick<AlarmPersonItem, 'deleted'> & Partial<Omit<AlarmPersonItem, 'deleted'>> & {_id: string, _active: boolean}
type AlarmTargetRecord = Pick<AlarmTargetItem, 'deleted'> & Partial<Omit<AlarmTargetItem, 'deleted'>> & {_id: string, _active: boolean}
type CreateForm = Partial<Omit<CreateApi, 'alarmTarget' | 'alarmPerson'> & {alarmTarget?: AlarmTargetRecord[], alarmPerson: AlarmPersonRecord[]}>
type EditForm = Partial<Omit<EditApi, 'alarmTarget' | 'alarmPerson'> & {alarmTarget?: AlarmTargetRecord[], alarmPerson?: AlarmPersonRecord[]}>
const init = async () => {
const getDetail = (): Promise<Detail> => {
throw new Error('unimplemented')
}
const detail = await getDetail()
const createForm: CreateForm = {
...detail,
}
} playground here I know that the reason which causes type incompatible is because of the alarmTarget and alarmPerson are different between CreateForm and Detail, but it still need to take a few minutes to find out what the differences are, what i want to know is that are there some good ways or tools can help us locating the type incompatible problem more easily? thanks. |
In the playground, the elaboration is fairly detailed and tells the full path of mismatched properties. |
To be fair, the signal-to-noise ratio in that elaboration is pretty low because it's all object literal types. |
Yeah. It would probably be more readable if more of these types were defined as interface containing other interfaces rather than a deeply-nested literal type with aliases picking pieces out. |
interface AlarmPerson { personName: string, concatInfo: string, deleted: boolean }
interface ProjectAlarmTarget {
deleted: boolean
managementDep: number
associatedProjectId: number
}
interface TableAlarmTarget {
deleted: boolean
managementDep: number
dataSetId: number
}
interface CreateApi {
alarmType: number
alarmLevel: number
alarmPerson: AlarmPerson[]
alarmTarget: (ProjectAlarmTarget | TableAlarmTarget)[]
}
interface EditAlarmPerson extends AlarmPerson {
id?: number
}
interface EditProjectAlarmTarget extends ProjectAlarmTarget {
id?: number
}
interface EditTableAlarmTarget extends TableAlarmTarget {
id?: number
}
interface EditApi {
id: number
alarmType: number
alarmLevel: number
alarmPerson: EditAlarmPerson[]
alarmTarget: (EditProjectAlarmTarget | EditTableAlarmTarget)[]
}
interface DetailAlarmTarget {
id: number, managementDep: number, dataSetId?: number, associatedProjectId?: number, deleted: boolean
}
interface DetailAlarmPerson {
id: number, personName: string, concatInfo: string, deleted: boolean
}
interface Detail {
id: number
alarmTarget: DetailAlarmTarget[]
alarmPerson: DetailAlarmPerson[]
alarmType: number
alarmLevel: number
createTime: number
}
interface AlarmPersonRecord {
id?: number, personName?: string, concatInfo?: string, deleted: boolean, _id: string, _active: boolean
}
interface AlarmTargetRecord {
id?: number, managementDep?: number, dataSetId?: number, associatedProjectId?: number, deleted: boolean, _id: string, _active: boolean
}
interface CreateForm {
alarmType?: number
alarmLevel?: number
alarmPerson?: AlarmPersonRecord[]
alarmTarget?: DetailAlarmTarget[]
}
interface EditForm {
id: number
alarmType?: number
alarmLevel?: number
alarmPerson?: AlarmPersonRecord[]
alarmTarget?: AlarmTargetRecord[]
}
const init = async () => {
const getDetail = (): Promise<Detail> => {
throw new Error('unimplemented')
}
const detail = await getDetail()
const createForm: CreateForm = {
...detail,
}
} playground here I have replaced all type aliases and object literal types with interfaces, and now the error messages are simpler and clearer. However, due to the large number of interfaces I have written, I am finding it difficult to remember some of the interface names. Is there a best practice for deciding when to choose between using an interface and a type? |
This issue has been marked as "Question" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
@Mng12345 https://www.typescriptlang.org/tsconfig#noErrorTruncation There’s also a future feature being discussed and designed that might allow you to interactively expand truncations in VS Code. |
@andrewbranch I found that noErrorTruncation can cause ordinary hover tooltips to slow down significantly. |
May be we can push this function into the tooltips dialog, let it expanding by user. |
Acknowledgement
Comment
Here the type of form is:
The type
CreateForm
andEditForm
are complicated, from the screen-shot, it says that the value type of form is not compatible, it took me a few minutes to figure out the reason, but still can not found it.The text was updated successfully, but these errors were encountered: