locate txt locates all files (of any type including regular, symlink, directory, socket...) whose path contains txt¹, so includes /foo/xtxty/bar, /foo/bar.txt, /foo/txt.bar, etc.
locate *.txt is wrong because that * is left unquoted, so the *.txt would be expanded by the shell to all the filenames in the current directory matching that pattern first and the result passed to locate, so for instance, if the current directory contained a.txt and b.txt, that would end up running locate a.txt b.txt which locates paths that contain either a.txt and b.txt or depending on the locate implementation, both of them such as /foo/da.txtob.txt (yours looking like it's one in the first category and you likely ran the command from within /home/abc).
If there's no .txt file in the current directory, depending on the shell you get either an error or locate is called with *.txt literally as argument.
To always call locate with a literal *.txt which is what you want here, you want to make sure that * is quoted for the shell, either with "...", '...' or backslash if in a Bourne-like shell, single quotes being the best as they quote every character in Bourne-like shell and are the most portable among shells:
locate '*.txt'
Then, as that argument contains a wildcard (*), locate switches from a subtstring search to a pattern matching search (same ones as those recognised by the shell or find -name for instance) and returns all the file paths that match that pattern, that is, all the file paths that end in .txt, like /foo/.txt or /foo/bar.txt.
locate is not a standard command, and there are many incompatible implementations around, but those simple behaviours above are common to most if not all. Most implementations support various options to do the matching differently. Check your own locate documentation with man locate, not some random pages on the internet as they may very well document a different implementation and/or version.
¹ and that did exist at the time the locate database was last updated